Core Layout Widgets
Row, Column, and Flex
Section titled “Row, Column, and Flex”Row and Column lay children out along one axis — horizontal and vertical. Both are just Flex with the direction fixed. You control alignment with mainAxisAlignment (along the axis) and crossAxisAlignment (across it).
Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, // along the vertical axis crossAxisAlignment: CrossAxisAlignment.start, // across (horizontal) children: const [ Text('top'), Text('middle'), Text('bottom') ],)A Column is unbounded along its main axis unless constrained (recall the ListView error from the last lesson). It sizes itself to its children by default (MainAxisSize.max fills, MainAxisSize.min shrinks).
Expanded and Flexible: dividing the free space
Section titled “Expanded and Flexible: dividing the free space”Inside a Row/Column, Expanded and Flexible split the remaining space by a flex factor. This is how you build proportional layouts.
Row( children: [ Expanded(flex: 2, child: blueBox), // takes 2/3 of the free space Expanded(flex: 1, child: redBox), // takes 1/3 ],)The difference: Expanded forces the child to fill its share (a tight constraint), while Flexible lets the child be up to its share but no larger (a loose one). Reach for Expanded when you want the child to stretch, Flexible when you want it to take at most a share.
Stack and Positioned: overlapping children
Section titled “Stack and Positioned: overlapping children”Stack layers children on top of each other; Positioned pins a child to edges of the stack. This is how you build badges, overlays, and custom placements.
Stack( children: [ const Avatar(), Positioned( right: 0, top: 0, child: const Badge(), // pinned to the top-right corner ), ],)Non-positioned children are sized to the stack and aligned by its alignment; positioned ones are placed by their edge offsets.
Container and the single-purpose helpers
Section titled “Container and the single-purpose helpers”Container is a convenience that composes several simpler widgets — padding, margin, decoration, constraints, alignment — into one. It is handy, but under the hood it is just a stack of Padding, DecoratedBox, ConstrainedBox, and Align.
flowchart LR container["Container"] --> align["Align"] container --> pad["Padding"] container --> deco["DecoratedBox"] container --> box["ConstrainedBox"]
For a single job, prefer the single-purpose widget — it is clearer and often lets you keep a const constructor:
Padding— insets only.SizedBox— fixed size (or aconst SizedBox(height: 8)as a cheap spacer).Center/Align— positioning.DecoratedBox— background/border only.