banner
jzman

jzman

Coding、思考、自觉。
github

Detailed Explanation of Flex Layout in Flutter Series

PS: Long-term persistence is a difficult thing.

Flutter is a cross-platform UI framework launched by Google that allows for the rapid development of high-quality applications on Android and iOS. Its main features include the ability for fast development, expressive and flexible UI, and good native performance. This article mainly introduces the Flex layout in Flutter, as follows:

  1. Basics of Flex
  2. Common Settings of Flex
  3. Row and Column
  4. Expanded and Flexible
  5. Spacer
  6. Summary

Basics of Flex#

The Flex layout method has been widely used in front-end and mini-program development. If you have previously learned about Flex layout, it is quite similar in Flutter. The diagram of the Flexible Box is as follows:

image

For an introduction to this image, please refer to the previous article:

The Flex Widget can set the main axis direction. If you know the main axis direction, you can directly use Row or Column. The Flex Widget cannot scroll; if scrolling is involved, you can try using ListView. If the content of the Flex Widget exceeds its width and height, a yellow-black striped warning will be displayed. For example, the error message that appears in the horizontal direction is as follows:

I/flutter (14749): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter (14749): The following assertion was thrown during layout:
I/flutter (14749): A RenderFlex overflowed by 440 pixels on the right.

The error display is as follows:

image

Common Settings of Flex#

The common properties of Flex are as follows:

  1. direction
  2. mainAxisAlignment
  3. mainAxisSize
  4. crossAxisAlignment
  5. verticalDirection
  6. textBaseline

direction#

Sets the main axis direction, with possible values of Axis.horizontal and Axis.vertical. The cross axis is perpendicular to the main axis direction.

mainAxisAlignment:#

Sets the arrangement of child Widgets along the main axis direction, with the default being MainAxisAlignment.start. The possible arrangements are as follows:

  • MainAxisAlignment.start: left-aligned, default value;
  • MainAxisAlignment.end: right-aligned;
  • MainAxisAlignment.center: centered;
  • MainAxisAlignment.spaceBetween: spaced at both ends;
  • MainAxisAlignment.spaceAround: equal spacing on both sides of each Widget, with the spacing to the screen edge being half of the spacing between other Widgets;
  • MainAxisAlignment.spaceEvenly: evenly distributed Widgets, with the spacing to the screen edge equal to the spacing between other Widgets.

The comparison effect is as follows:

image

mainAxisSize#

Sets the size of the main axis, with the default being MainAxisSize.max. The possible values are as follows:

  • MainAxisSize.max: the size of the main axis is the size of the parent container;
  • MainAxisSize.min: the size of the main axis is the sum of the sizes of its child Widgets.

The comparison effect is as follows:

image

Setting mainAxisAlignment to spaceBetween, if mainAxisSize is set to max, it arranges according to spaceBetween based on the entire Row width. If mainAxisSize is set to min, it arranges according to spaceBetween within the sum of the widths of the three Containers.

crossAxisAlignment#

Sets the arrangement of child Widgets along the cross axis direction, with the default being CrossAxisAlignment.center. The possible arrangements are as follows:

  • CrossAxisAlignment.start: aligned with the starting position of the cross axis;
  • CrossAxisAlignment.end: aligned with the ending position of the cross axis;
  • CrossAxisAlignment.center: centered;
  • CrossAxisAlignment.stretch: fills the entire cross axis;
  • CrossAxisAlignment.baseline: aligned according to the baseline of the first line of text.

The comparison effect is as follows:

image

verticalDirection#

Sets the arrangement order of child Widgets in the vertical direction, with the default being VerticalDirection.down. The possible settings are as follows:

  • VerticalDirection.down: start at the top, end at the bottom;
  • VerticalDirection.up: start at the bottom, end at the top.

The comparison effect is as follows:

image

Observe the cross axis setting of CrossAxisAlignment.end and the changes in the vertical direction based on this.

textBaseline#

Sets the baseline type for text alignment, with the possible values as follows:

  • TextBaseline.alphabetic: aligned with the alphabetic baseline;
  • TextBaseline.ideographic: aligned with the ideographic character baseline;

When using it, if crossAxisAlignment is set to baseline, the textBaseline property must be set. The usage is as follows:

// textBaseline
class FlexSamplePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flex Sample"),
        centerTitle: true,
      ),
      body: Row(
        children: <Widget>[
          Expanded(
              child: Row(
                children: <Widget>[
                  Text("躬",style: TextStyle(fontSize: 40,),),
                  Text("x",style: TextStyle(fontSize: 60,),),
                  Text("ing",style: TextStyle(fontSize: 16,),),
                  Text("之",style: TextStyle(fontSize: 16,),),
                ],
          )),
          Expanded(
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.baseline,
                textBaseline: TextBaseline.alphabetic,
                children: <Widget>[
                  Text("躬",style: TextStyle(fontSize: 40,),),
                  Text("x",style: TextStyle(fontSize: 60,),),
                  Text("ing",style: TextStyle(fontSize: 16,),),
                  Text("之",style: TextStyle(fontSize: 16, ),),
                ],
          )),
          Expanded(
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.baseline,
                textBaseline: TextBaseline.ideographic,
                children: <Widget>[
                  Text("躬",style: TextStyle(fontSize: 40, ),),
                  Text("x",style: TextStyle(fontSize: 60,),),
                  Text("ing",style: TextStyle(fontSize: 16,),),
                  Text("之",style: TextStyle(fontSize: 16,),),
                ],
              ))
        ],
      ),
    );
  }
}

Comparing the effects of not setting the textBaseline property, setting TextBaseline.alphabetic, and TextBaseline.ideographic is as follows:

image

Although the two have different meanings regarding the corresponding baselines, no differences were found in testing. Further observation will continue, and friends who know can comment and point it out.

Row and Column#

Row and Column both inherit from Flex. The main axis direction of Row is horizontal, while the main axis direction of Column is vertical, which means that the main axis direction is set based on Flex, as follows:

// Row
direction: Axis.horizontal,
/// Column
direction: Axis.vertical,

If the main axis direction is determined, you can directly use Row or Column. The usage is consistent with Flex.

Expanded and Flexible#

The fix property of Flexible defaults to FlexFit.loose, while Expanded inherits from Flexible, and its fix property is specified as FlexFit.tight. The two differ because of their fix properties. If the fit property of Flexible is set to FlexFit.tight, then Flexible is equivalent to Expanded. The possible fit properties are as follows:

  • tight: forces filling the available space;
  • loose: does not force filling the available space, Widget's own size.

The comparison effect is as follows:

image

Expanded allows components within Row, Column, or Flex to fill the available space along the main axis. If multiple Widgets use the Expanded component, the flex property of Expanded can be used to allocate the main axis space proportionally. The flex property is equivalent to the weight property of Android's LinearLayout, as follows:

// Expanded
class ExpandedSamplePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("Row Sample"),
          centerTitle: true,
        ),
        body: Row(
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.max,
          children: <Widget>[
            Expanded(
              flex: 1,
              child: Container(
                  width: 50,
                  height: 50,
                  color: Colors.red,
                  child: Center(
                    child: Text(
                      "A",
                      style: TextStyle(fontSize: 20, color: Colors.white),
                    ),
                  )),
            ),
            Expanded(
              flex: 2,
              child: Container(
                  width: 50, // Width of Row Expanded is ineffective
                  height: 50, // Height of Column Expanded is ineffective
                  color: Colors.green,
                  child: Center(
                    child: Text(
                      "B",
                      style: TextStyle(fontSize: 20, color: Colors.white),
                    ),
                  )),
            ),
            Container(
                width: 50,
                height: 50,
                color: Colors.yellow,
                child: Center(
                  child: Text(
                    "C",
                    style: TextStyle(fontSize: 20, color: Colors.white),
                  ),
                )),
          ],
        ));
  }
}

The display effect is as follows:

image

Spacer#

Spacer is used to adjust the spacing between Widgets and will occupy all remaining space. Therefore, the settings of MainAxisAlignment will be ineffective. The flex property of Spacer is used to set the allocation weight of the remaining space, with a default value of 1, indicating that it occupies all remaining space. If there are two or more Spacers, the remaining space will be allocated according to flex. The code reference is as follows:

class RowSamplePage1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("Row Sample"),
          centerTitle: true,
        ),
        body: ConstrainedBox(
          constraints: BoxConstraints(maxHeight: 150),
          child: Row(
            children: <Widget>[
              Container(
                width: 80,
                height: 80,
                color: Colors.red,
              ),
              Spacer(flex: 1,),
              Container(
                width: 80,
                height: 80,
                color: Colors.green,
              ),
              Spacer(flex: 2,),
              Container(
                width: 80,
                height: 80,
                color: Colors.yellow,
              ),
            ],
          ),
        ));
  }
}

The display effect is as follows:

image

The above mainly covers the relevant content of the Flex layout in Flutter, focusing on understanding the basic concepts of Flex, and based on this, learning and verifying the Flex layout.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.