Containers

What are the container building blocks?

  • Flex is the base class for Row and Column. It implements the flex layout protocol in an axis-agnostic manner.

  • Row is identical to Flex with a default axis of Axis.horizontal.

  • Column is identical to Flex with a default axis of Axis.vertical.

  • Flexible is the base class for Expanded. It is a parent data widget that alters its child’s flex value. Its default fit is FlexFit.loose, which causes its child to be laid out with loose constraints

  • Expanded is identical to Flexible with a default fit of FlexFit.tight. Consequently, it passes tight constraints to its children, requiring them to fill all available space.

How are flex-based containers laid out?

  • All flexible containers follow the same protocol.

    • Layout children without flex factors with unbounded main constraints and the incoming cross constraints (if stretching, cross constraints are tight).

    • Apportion remaining space among flex children using flex factors.

      • Main axis size = myFlex * (freeSpace / totalFlex)

    • Layout each child as above, with the resulting size as the main axis constraint. Use tight constraints for FlexFit.tight; else, use loose.

    • The cross extent is the max of all child cross extents.

    • If using MainAxisSize.max, the main extent is the incoming max constraint. Else, the main extent is the sum of all child extents in that dimension (subject to constraints).

    • Children are positioned according to MainAxisAlignment and CrossAxisAlignment.

How are containers laid out?

  • In short, containers size to their child plus any padding; in so doing, they respect any additional constraints provided directly or via a width or height. Decorations may be painted over this entire region. Next, a margin is added around the resulting box and, if specified, a transformation applied to the entire container.

    • If there is no child and no explicit size, the container shrinks in unbounded environments and expands in bounded ones.

  • The container widget delegates to a number of sub-widgets based on its configuration. Each behavior is layered atop all previous layers (thus, child refers to the accumulation of widgets). If a width or height is provided, these are transformed into extra constraints.

    • If there is no child and no explicit size:

      • Shrink when the incoming constraints are unbounded (via LimitedBox); else, expand (via ConstrainedBox).

    • If there is an alignment:

      • Align the child within the parent (via Align).

    • If there is padding or the decoration has padding...

      • Apply the total padding to the child (via Padding).

    • If there is a decoration:

      • Wrap the child in the decoration (via DecoratedBox).

    • If there is a foreground decoration:

      • Wrap the child in the foreground decoration (via DecoratedBox, using DecorationPosition.foreground).

    • If there are extra constraints:

      • Apply the extra constraints to the incoming constraints (via ConstrainedBox).

    • If there is a margin...

      • Apply the margin to the child (via Padding).

    • If there is a transform...

      • Transform the child accordingly (via Transform).