Let's learn flutter's layout components together

1. Linear layout

Our commonly used linear layout mainly has two components Row and Column.
The so-called linear layout refers to arranging subcomponents along the horizontal or vertical direction. Flutter uses Row and Column to implement linear layout, similar to the LinearLayout control in Android. Both Row and Column inherit from Flex

Row({
  ...  
  TextDirection textDirection,    
  MainAxisSize mainAxisSize = MainAxisSize.max,    
  MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
  VerticalDirection verticalDirection = VerticalDirection.down,  
  CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
  List<Widget> children = const <Widget>[],
})

2. Flexible layout

Flexible layout allows child components to allocate parent container space according to a certain ratio.
The elastic layout in flutter is mainly realized through the cooperation of Flex and Expanded/Flexible.

Flex components can arrange sub-components along the horizontal or vertical direction. If you know the main axis direction, it is more convenient to use Row or Column, because both Row and Column inherit from Flex, and the parameters are basically the same, so basically you can use Flex. Use Row or Column. Flex itself is very powerful, and it can also cooperate with Expanded components to achieve elastic layout. The Expanded component can expand subcomponents such as Row, Column, and Flex in the direction of its main axis and fill the available space.
Expanded inherits from Flexible. The same point between Flexible and Expanded is that they must be used in Row, Column, and Flex, and can be used to configure subcomponents. Scale (weight) adaptation of the layout.
The difference is that Expanded will force the remaining blank space to be filled, while Flexible will not force it to be filled

Row(
          children: <Widget>[
            Container(
              height: 30.0,
              width: 48.0,
              color: Colors.red,
            ),
            Flexible(
              flex: 1,
              child: Container(
                height: 30.0,
                width: 88.0,
                color: Colors.green,
              ),
            ),
          ],
        ),

insert image description here

Row(
          children: <Widget>[
            Container(
              height: 30.0,
              width: 48.0,
              color: Colors.red,
            ),
            Expanded(
              flex: 1,
              child: Container(
                height: 30.0,
                width: 88.0,
                color: Colors.green,
              ),
            ),
          ],
        ),

insert image description here

3. Flow layout

When using row, if there is too much content in one row, an error will be reported on the overflow part on the right. This is because Row has only one line by default, and it will not wrap if it exceeds the screen. We call a layout that automatically wraps beyond the screen display range as a fluid layout. Flutter supports flow layout through Wrap and Flow. After replacing the Row in the above example with Wrap, the overflow part will automatically wrap. Wrap
: We can see that many properties of Wrap are also available in Row (including Flex and Column). , such as direction, crossAxisAlignment, textDirection, verticalDirection, etc., these parameters have the same meaning,

Wrap({
    
    
  ...
  this.direction = Axis.horizontal,
  this.alignment = WrapAlignment.start,
  this.spacing = 0.0,
  this.runAlignment = WrapAlignment.start,
  this.runSpacing = 0.0,
  this.crossAxisAlignment = WrapCrossAlignment.start,
  this.textDirection,
  this.verticalDirection = VerticalDirection.down,
  List<Widget> children = const <Widget>[],
})
 Wrap(
          spacing: 8.0, // 主轴(水平)方向间距
          runSpacing: 4.0, // 纵轴(垂直)方向间距
          alignment: WrapAlignment.center, //沿主轴
          children: <Widget>[
            for (int i = 0; i < 8; i++)
              Container(
                height: 30.0,
                color: Colors.red,
                child: Text("我是Wrap"),
              ),
          ],
        ),

insert image description here

Flow component
We generally seldom use Flow, because it is too complicated and needs to realize the position conversion of sub-widgets by ourselves. In many scenarios, the first thing to consider is whether Wrap meets the requirements. Flow is mainly used in some scenarios that require custom layout strategies or high performance requirements (such as in animation). Flow has the following advantages:

Good performance; Flow is a very efficient control for adjusting the size and position of sub-components. Flow uses the transformation matrix to optimize the position adjustment of sub-components: after Flow is positioned, if the size or position of sub-components changes , call context.paintChild in the paintChildren() method in FlowDelegate to redraw, and context.paintChild uses the transformation matrix when redrawing, and does not actually adjust the component position.
Flexible; since we need to implement the paintChildren() method of FlowDelegate by ourselves, we need to calculate the position of each component by ourselves, so we can customize the layout strategy.
Disadvantages:
complicated to use.
Flow cannot adapt to the size of subcomponents, and must return a fixed size by specifying the size of the parent container or implementing getSize of TestFlowDelegate.

Four, cascading layout

Cascading layout, as the name suggests, allows widgets to be stacked together.
stack component

Stack({
    
    
  this.alignment = AlignmentDirectional.topStart,
  this.textDirection,
  this.fit = StackFit.loose,
  this.overflow = Overflow.clip,
  List<Widget> children = const <Widget>[],
})

alignment: This parameter determines how to align subcomponents that are not positioned (Positioned is not used) or partially positioned. The so-called partial positioning here specifically refers to not positioning on a certain axis: left/right is the horizontal axis, top/bottom is the vertical axis, as long as it contains a positioning attribute on a certain axis, it is considered to be positioned on that axis.
textDireaction: Same as the textDirection function of Row and Wrap, it is used to determine the reference system of alignment alignment, that is, if the value of textDirection is TextDirection.ltr, the start of alignment represents left, and end represents right, that is, the order from left to right; The value of textDirection is TextDirection.rtl, then the start of the alignment represents the right, and the end represents the left, that is, the order from right to left.
fit: This parameter is used to determine how unpositioned subcomponents fit into the size of the Stack. StackFit.loose means to use the size of the subcomponent, and StackFit.expand means to expand to the size of the Stack.
overflow: This property determines how to display subcomponents that exceed the display space of the Stack; when the value is Overflow.clip, the excess part will be clipped (hidden), and when the value is Overflow.visible, it will not.

Positioned component

const Positioned({
    
    
  Key key,
  this.left, 
  this.top,
  this.right,
  this.bottom,
  this.width,
  this.height,
  @required Widget child,
})

left, top, right, and bottom represent the distances from the left, top, right, and bottom sides of the Stack, respectively. Width and height are used to specify the width and height of the element to be positioned. Note that the meaning of the width and height of Positioned is slightly different from other places. Here it is used to position components with left, top, right, and bottom. For example, in the horizontal direction, you can only specify left, right, and width For two of the three attributes, if you specify left and width, right will automatically calculate (left+width). If you specify three attributes at the same time, an error will be reported. The same is true for the vertical direction.

Container(
        height: 400,
        width: double.infinity,
        child: Stack(
          alignment: Alignment.center,
          children: <Widget>[
            Container(
              height: 30.0,
              color: Colors.red,
              child: Text("我是Stack"),
            ),
            Positioned(
              top: 50,
              left: 100,
              child: Container(
                height: 50,
                width: 50,
                color: Colors.red,
              ),
            )
          ],
        ),
      ),

Look at the renderings:
insert image description here

5. Relative layout

Align component

Align({
    
    
  Key key,
  this.alignment = Alignment.center,
  this.widthFactor,
  this.heightFactor,
  Widget child,
})

alignment : Requires a value of AlignmentGeometry type, indicating the starting position of the child component in the parent component. AlignmentGeometry is an abstract class that has two commonly used subclasses: Alignment and FractionalOffset, which we will describe in detail in the examples below.
widthFactor and heightFactor are attributes used to determine the width and height of the Align component itself; they are two scaling factors that will be multiplied by the width and height of the child element respectively, and the final result is the width and height of the Align component. If the value is null, the component's width and height will take up as much space as possible.

 Container(
        height: 400,
        color: Colors.blue,
        width: double.infinity,
        child: Align(
          alignment: Alignment.center,
          child: Container(
            height: 30.0,
            color: Colors.red,
            child: Text("我是Align"),
          ),
        ),
      ),

insert image description here

6. Summary

After writing so many layout components, it is considered finished. We need to use corresponding layout components according to different scenarios, and you will master it soon if you are smart. If it is useful to you, please manually like it, your like is the motivation for me to write.

Guess you like

Origin blog.csdn.net/hjjdehao/article/details/126012159