Introduction

For a front-end framework, in addition to the various components, the most important thing is the layout of connecting these components. The English name of the layout is layout, which is a constraint used to describe how to place components.

In flutter, basically all objects are widgets, and layouts are no exception. That is to say, the layout in flutter is also done with code, which is different from other languages that use configuration files to describe layout.

You can think of a layout as an invisible widget. These invisible widgets are used to act on visible widget objects and impose some restrictions on them.

Classification of layout in flutter

There are many layout widgets in flutter, and they can be roughly divided into three categories: layout widgets that contain only one child, layout widgets that can contain multiple children, and slidable Sliver widgets.

There are also many specific implementations of these three layouts. For Single-child layout widgets, the following widgets are included:

  • Align -- used to operate on the components it contains.
  • AspectRatio -- Scale the components in it.
  • Baseline -- Positioning by using the baseline of the child component.
  • Center -- Since the component is in the center.
  • ConstrainedBox -- Similar to the constraint in IOS, it represents the constraints of subcomponents.
  • Container -- A commonly used widget that can be used to contain multiple other widgets.
  • CustomSingleChildLayout -- defers the layout of its individual children.
  • Expanded -- expands the Row, Column or Flex child.
  • FittedBox -- Scale and position its children according to fit.
  • FractionallySizedBox -- Resize the child according to the total available space.
  • IntrinsicHeight -- a widget that adjusts its child to the child's intrinsic height.
  • IntrinsicWidth -- A widget that adjusts its child to the child's intrinsic width.
  • LimitedBox -- limit the size of a box.
  • Offstage -- puts the child in the render tree, but doesn't trigger any repaints.
  • OverflowBox -- Allows children to override the parent's limits.
  • Padding -- provide padding for the child.
  • SizedBox -- The box of the given size.
  • SizedOverflowBox -- A box that can override the limits of the parent component.
  • Transform -- Child components can be transformed.

The above is a layout component that contains a single child, and the following is a layout component that can contain multiple children:

  • Column -- Represents a column of children.
  • CustomMultiChildLayout -- uses delegates to position and scale child components.
  • Flow -- Flow layout.
  • GridView -- grid layout.
  • IndexedStack -- Displays one child from a series of children.
  • LayoutBuilder -- a widget tree that can depend on the size of the parent component.
  • ListBody -- Layout children according to the given axis.
  • ListView -- a scrollable list.
  • Row -- Represents a row of children.
  • Stack -- Components in a stack layout.
  • Table -- Component in the form of a table.
  • Wrap -- A widget that can dynamically adjust the child child.

The slidable Sliver widgets are as follows:

  • CupertinoSliverNavigationBar -- is an IOS style navigation bar.
  • CustomScrollView -- A ScrollView that can customize the scroll effect.
  • SliverAppBar -- a material-style app bar that includes a CustomScrollView.
  • SliverChildBuilderDelegate -- Use the builder callback to provide the child's delegate to slivers.
  • SliverChildListDelegate -- use list to provide children's delegate for livers.
  • SliverFixedExtentList -- sliver with fixed axis extent.
  • SliverGrid -- child is a sliver with a two-dimensional distribution.
  • SliverList -- child is a sliver for linear layout.
  • SliverPadding -- A sliver that provides padding.
  • SliverPersistentHeader -- variable size sliver.
  • SliverToBoxAdapter -- Sliver containing a single box widget.

Common layout examples

We listed all the flutter layouts above, and they almost meet all the layout requirements we will use in the program. Here we take the two most basic and commonly used layouts: Row and Column as examples to explain the layout in detail. use.

Both Row and Column belong to the multiple child layout widgets mentioned above, which can contain multiple other widget components.

Let's first look at the definitions of Row and column.

 class Row extends Flex {
  Row({
    Key? key,
    MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
    MainAxisSize mainAxisSize = MainAxisSize.max,
    CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
    TextDirection? textDirection,
    VerticalDirection verticalDirection = VerticalDirection.down,
    TextBaseline? textBaseline, // NO DEFAULT: we don't know what the text's baseline should be
    List<Widget> children = const <Widget>[],
  }) : super(
    children: children,
    key: key,
    direction: Axis.horizontal,
    mainAxisAlignment: mainAxisAlignment,
    mainAxisSize: mainAxisSize,
    crossAxisAlignment: crossAxisAlignment,
    textDirection: textDirection,
    verticalDirection: verticalDirection,
    textBaseline: textBaseline,
  );
}
 class Column extends Flex {
  Column({
    Key? key,
    MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
    MainAxisSize mainAxisSize = MainAxisSize.max,
    CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
    TextDirection? textDirection,
    VerticalDirection verticalDirection = VerticalDirection.down,
    TextBaseline? textBaseline,
    List<Widget> children = const <Widget>[],
  }) : super(
    children: children,
    key: key,
    direction: Axis.vertical,
    mainAxisAlignment: mainAxisAlignment,
    mainAxisSize: mainAxisSize,
    crossAxisAlignment: crossAxisAlignment,
    textDirection: textDirection,
    verticalDirection: verticalDirection,
    textBaseline: textBaseline,
  );
}

It can be seen that both Row and Column inherit from Flex, and their construction methods call the construction method of Flex. The difference between the two is that the direction is different. The direction of Row is Axis.horizontal, and the direction of Column is Axis.vertical .

So what is Flex?

Flex is a widget, and subcomponents in Flex will be displayed in a specified direction. This direction can be controlled, such as horizontal or vertical. If you already know the direction of the main axis in advance, you can use Row or Column instead of Flex, because it is more concise.

In Flex, if you want a child to fill the available space in a certain direction, you can wrap the child in Expanded.

It should be noted that Flex is not scrollable. If there are too many children in Flex that exceed the available space in Flex, then Flex will report an error, so if you need to display a lot of children, you can consider using scrollable Components, such as ListView.

If you only have one child, then there is no need to use Flex or Row and Column. Consider using Align or Center to position the child.

There are several very important parameters in Flex. For example, mainAxisAlignment represents the arrangement rule of subcomponents along the main axis direction, mainAxisSize represents the size of the main axis, and crossAxisAlignment represents the arrangement rule of subcomponents along the vertical axis of the main axis. Of course, it also has its most important children property. Children is a list of Widgets used to store the child components to be displayed.

Taking Row as an example, we create a simple RowWidget:

 class RowWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      textDirection: TextDirection.ltr,
      children: [
        YellowBox(),
        YellowBox(),
        YellowBox(),
      ],
    );
  }
}

Here we return a Row object with the textDirection and children properties set.

Inside the children is a custom YellowBox:

 class YellowBox extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 50,
      height: 50,
      decoration: BoxDecoration(
        color: Colors.yellow,
        border: Border.all(),
      ),
    );
  }
}

A YellowBox is a square with a length and width of 50. Here we use BoxDecoration to color it.

Finally, put the RowWidget into the Scaffold's body, as shown below:

 Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: RowWidget()
    );
  }

We can see the image below:

You can see that the YellowBox is close together, what if we want to separate it evenly?

We can add a property called mainAxisAlignment to Row with the following values:

 mainAxisAlignment: MainAxisAlignment.spaceEvenly

Re-run, the resulting image is as follows:

We also mentioned an Expanded component above, which can be used to fill the remaining available space. We surrounded the last YellowBox with Expanded, as shown below:

 return Row(
      textDirection: TextDirection.ltr,
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        YellowBox(),
        YellowBox(),
        Expanded(
          child: YellowBox(),
        )
      ],
    );

The resulting image is as follows:

You can see that the last Box is filled to the remaining space of the entire Row.

Everyone should pay attention that at this time mainAxisAlignment has no effect.

If you observe the constructor of Expanded, you can see that Expanded also has a flex property:

 const Expanded({
    Key? key,
    int flex = 1,
    required Widget child,
  }) : super(key: key, flex: flex, fit: FlexFit.tight, child: child);

The flex property represents the flex factor, and the default value is 1. In the above example, we adjust the flex to 2 to see the effect:

 children: [
        YellowBox(),
        YellowBox(),
        Expanded(
          flex:2,
          child: YellowBox(),
        )
      ],

The result of running is the same as flex=1, why?

In fact, this flex represents the proportion of space occupied by other Expanded components. We can say that all subcomponents are expanded with Expanded, and then look at the effect:

 children: [
        Expanded(
          child: YellowBox(),
        ),
        Expanded(
          child: YellowBox(),
        ),
        Expanded(
          flex: 2,
          child: YellowBox(),
        )
      ],

The results are as follows:

You can see that the last child takes up twice as much space as the first two.

What if we want to add spaces in the middle of YellowBox? There are two ways.

The first way is to use SizedBox, as follows:

 children: [
        Expanded(
          child: YellowBox(),
        ),
        SizedBox(
          width: 100,
        ),
        Expanded(
          child: YellowBox(),
        ),
        Expanded(
          flex: 2,
          child: YellowBox(),
        )
      ],

The SizedBox can contain child children to reset the length and height of the child child. If no child child is included, a space will be generated.

Another way is to use Spacer, like this:

 children: [
        Expanded(
          child: YellowBox(),
        ),
        Spacer(flex: 2),
        Expanded(
          child: YellowBox(),
        ),
        Expanded(
          flex: 2,
          child: YellowBox(),
        )
      ],

The resulting image is as follows:

Both Spacer and SizedBox can generate blanks, the difference is that Spacer can be used with flex, while SizedBox must have a fixed size.

Summarize

The above is the classification of layout and layout in flutter and the usage of basic layout Row and Column.

Example from this article: https://github.com/ddean2009/learn-flutter.git

For more information, please refer to http://www.flydean.com/07-flutter-ui-layout-overview/

The most popular interpretation, the most profound dry goods, the most concise tutorials, and many tricks you don't know are waiting for you to discover!

Welcome to pay attention to my official account: "Program those things", understand technology, understand you better!


flydean
890 声望433 粉丝

欢迎访问我的个人网站:www.flydean.com