We might have heard “Everything’s a Widget” in Flutter. But, do you understand how build() method of widget work? Let’s dig deep into that method to prove “Everything’s a Widget”.

Note: for non-paywall link of this article, let use: https://medium.com/fluttervn/how-build-method-of-flutter-widget-proves-everythings-a-widget-a49b5efc5cbb?source=friends_link&sk=f1c33cb455bf98104ff44585ef61553f

First, a typical widget such as Container would have constructor like this:

Container({

Key key,

this.alignment, // AlignmentGeometry

this.padding, // EdgeInsetsGeometry

Color color,

Decoration decoration,

this.foregroundDecoration,

double width,

double height,

BoxConstraints constraints,

this.margin,

this.transform,

this.child,

})

At the beginning I thought Container is a complex widget with these properties: alignment , padding , decoration , …

However in Flutter, we also have similar widgets, such as Align, Padding, DecoratedBox,… Do they have any relationship? To understand, we must look at build() method of Container:

@override

Widget build(BuildContext context) {

Widget current = child;



if (child == null && (constraints == null || !constraints.isTight)) {

current = LimitedBox(

maxWidth: 0.0,

maxHeight: 0.0,

child: ConstrainedBox(constraints: const BoxConstraints.expand()),

);

}



if (alignment != null)

current = Align(alignment: alignment, child: current);



final EdgeInsetsGeometry effectivePadding = _paddingIncludingDecoration;

if (effectivePadding != null)

current = Padding(padding: effectivePadding, child: current);



if (decoration != null)

current = DecoratedBox(decoration: decoration, child: current);



if (foregroundDecoration != null) {

current = DecoratedBox(

decoration: foregroundDecoration,

position: DecorationPosition.foreground,

child: current,

);

}



if (constraints != null)

current = ConstrainedBox(constraints: constraints, child: current);



if (margin != null)

current = Padding(padding: margin, child: current);



if (transform != null)

current = Transform(transform: transform, child: current);



return current;

}

Let’s analyze from top to bottom (assume that Container has full parameters):

We begin from the real child of widget, in this case is child (assume it’s Text). So, the current structure of Container tree is: Text .

(assume it’s Text). So, the current structure of Container tree is: . Next, if has align param, then wrap existing child into an Align widget → tree is: Align → Text . Otherwise if no align param, don’t wrap existing child into Align to avoid complexity/deep level of tree. Now, current child is the Align.

param, then wrap existing child into an Align widget → tree is: . Otherwise if no align param, don’t wrap existing child into Align to avoid complexity/deep level of tree. Now, current child is the Align. Next, if has padding param (of Container or from Decoration), then wrap current child into a Padding widget → tree is: Padding → Align → Text . Now, current child is the Padding.

param (of Container or from Decoration), then wrap current child into a Padding widget → tree is: . Now, current child is the Padding. Next, if has decoration param, then wrap current child into a DecoratedBox widget → tree is: DecoratedBox → Padding → Align → Text . Now, current child is the DecoratedBox.

param, then wrap current child into a DecoratedBox widget → tree is: . Now, current child is the DecoratedBox. Same for foregroundDecoration param → tree is: DecoratedBox → DecoratedBox → Padding → Align → Text . Now, current child is the DecoratedBox.

param → tree is: . Now, current child is the DecoratedBox. Next, if has constraints param, then wrap current child into a ConstrainedBox widget → tree is: ConstrainedBox → DecoratedBox → DecoratedBox → Padding → Align → Text . Now, current child is the ConstrainedBox.

. Now, current child is the ConstrainedBox. We have margin param, but there is no Margin widget, it’s Padding instead, however is placed near the root of Container → tree is: Padding → ConstrainedBox → DecoratedBox → DecoratedBox → Padding → Align → Text . Now, current child is the Padding.

param, but there is no Margin widget, it’s Padding instead, however is placed near the root of Container → tree is: . Now, current child is the Padding. Finally, with transform param, will wrap into Transform → tree is: Transform → Padding → ConstrainedBox → DecoratedBox → DecoratedBox → Padding → Align → Text .