Flutter layout (vii)-ROW, column detailed

Source: Internet
Author: User

This paper mainly introduces the row and column control in flutter layout, introduces its layout behavior and usage scene in detail, and analyzes the source code.

1. Row

A widget that displays it children in a horizontal array.

1.1 Introduction

A multi-child node control, which is very common in flutter, arranges children into one line. It is estimated that the flex layout is borrowed from the Web, so many properties and performance are similar. Note, however, that it does not have a scrolling property, and if one line is exceeded, an overflow prompt appears under Debug.

1.2 Layout behavior

The layout of row has six steps, which are shown from flex (the parent class of row and column):

    1. First, according to the unrestricted spindle (main axis) constraints, the flex is null or 0 of the child layout, and then follow the intersection axis (cross axis) constraints, the child is adjusted;
    2. The remaining space in the spindle direction is divided into equal portions according to the non-null flex value;
    3. For the above steps the flex value is not empty child, in the direction of the cross-axis adjustment, in the spindle direction using the maximum constraints, so that it fills the space of step 2;
    4. The Flex cross axis is derived from the maximum cross axis of the child node;
    5. The value of the spindle flex is determined by the Mainaxissize property, where mainaxissize can take Max, Min, and specific value values;
    6. The location of each child is determined by mainaxisalignment and crossaxisalignment.

The layout behavior of row has so many steps on the surface that it is simple enough to refer to the flex layout in the Web, including the concepts of spindles, cross axes, and so on.

1.3 Inheritance Relations
Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > MultiChildRenderObjectWidget > Flex > Row

Both row and column are subclasses of Flex, and their implementation is done by flex only, with different parameters.

1.4 Sample Code
Row(  children: <Widget>[    Expanded(      child: Container(        color: Colors.red,        padding: EdgeInsets.all(5.0),      ),      flex: 1,    ),    Expanded(      child: Container(        color: Colors.yellow,        padding: EdgeInsets.all(5.0),      ),      flex: 2,    ),    Expanded(      child: Container(        color: Colors.blue,        padding: EdgeInsets.all(5.0),      ),      flex: 1,    ),  ],)

A very simple example, using the expanded control, divides the width of a line into four equal parts, the first to third child occupies 1/4 of the area, the second child takes up 1/2 of the area, and is controlled by the Flex attribute.

1.5 Source Code parsing

The constructor functions are as follows:

Row({  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>[],})
1.5.1 Attribute parsing

mainaxisalignment: Alignment on the spindle direction, will work for the child's position, default is start.

Where Mainaxisalignment enumeration values:

    • Center: Place the Children in the centre of the spindle;
    • End: Place the children at the end of the spindle;
    • Spacearound: The blank area of the spindle direction is divided evenly, so that the white space between the children is equal, but the white space of the child is 1/2;
    • Spacebetween: Divide the blank area of the spindle direction, make the white space between the children equal, the end child is close to the head and tail, no gap;
    • Spaceevenly: Divide the blank area of the spindle direction, make the white space between the children equal, including the child;
    • Start: Place the children at the starting point of the spindle;

The difference between Spacearound, Spacebetween and Spaceevenly is the way to treat the child. The distance from the end of the distance is 1/2, 0, 1 of the blank area, respectively.

mainaxissize: A value that occupies space in the direction of the spindle, which is max by default.

There are two kinds of values for mainaxissize:

    • Max: Maximizes available space in the spindle direction based on the layout constraints passed in;
    • Min: In contrast to Max, it is the space available to minimize the spindle direction;

crossaxisalignment: Alignment of children in the direction of intersection, slightly different from mainaxisalignment.

There are several Crossaxisalignment enumeration values:

    • Baseline: In the direction of the cross axis, so that the children baseline alignment;
    • The Center:children is centered on the cross axis;
    • The End:children is displayed at the end of the cross axis;
    • The Start:children is displayed at the beginning of the crossing axis;
    • Stretch: Let children fill the direction of the cross axis;

textdirection: Compatible settings for the Arabic language system, generally no need to process.

verticaldirection: Defines the children placement order, which is down by default.

There are two types of Verticaldirection enumeration values:

    • Down: Layout from top to bottom;
    • Up: layout from bottom to top.

The top corresponds to row and column, the left and the top, the bottom, the right and the bottom.

textbaseline: There are two ways to use the Textbaseline, as described earlier.

1.5.2 Source

The source code for row and column is a constructor, and the implementation is all in their parent class flex.

About the Flex constructor

Flex({  Key key,  @required this.direction,  this.mainAxisAlignment = MainAxisAlignment.start,  this.mainAxisSize = MainAxisSize.max,  this.crossAxisAlignment = CrossAxisAlignment.center,  this.textDirection,  this.verticalDirection = VerticalDirection.down,  this.textBaseline,  List<Widget> children = const <Widget>[],})

As you can see, the Flex constructor has one more parameter than row and column. The difference between row and column is exactly the same as this direction parameter. When it is axis.horizontal, it is row, and when it is axis.vertical, it is column.

Let's take a look at the flex layout function, because the layout functions are much more, so the segments are explained:

while (child = null) {final Flexparentdata childparentdata = Child.parentdata;  totalchildren++;  Final int flex = _getflex (child);    if (Flex > 0) {totalflex + = Childparentdata.flex;  Lastflexchild = child;    } else {boxconstraints innerconstraints; if (crossaxisalignment = = crossaxisalignment.stretch) {switch (_direction) {case axis.horizontal:i nnerconstraints = new Boxconstraints (MinHeight:constraints.maxHeight, Maxh          Eight:constraints.maxHeight);        Break                                                Case Axis.vertical:innerConstraints = new Boxconstraints (MinWidth:constraints.maxWidth,          MaxWidth:constraints.maxWidth);      Break }} else {switch (_direction) {case Axis.horizontal:innerConstraints = new Boxconstraints (maxhe          Ight:constraints.maxHeight);        Break Case Axis.vertical:innerConstraints = new BoxconsTraints (MaxWidth:constraints.maxWidth);      Break    }} child.layout (Innerconstraints, parentusessize:true);    Allocatedsize + = _getmainsize (child);  Crosssize = Math.max (crosssize, _getcrosssize (child)); } child = Childparentdata.nextsibling;}

The above code, I have some of the middle of the assert and error messages such as the code removed, do not affect the actual understanding.

At the beginning of the layout, the child is traversed first, and the traversal has a function of two points:

    • For child with flex values, calculate Flex's and find the last child that contains flex values. Find this child, because the spindle alignment, it may be the position of the adjustment, need to find out;
    • For a child that does not contain flex, the child is adjusted according to the cross-axis direction setting.
Final double freeSpace = Math.max (0.0, (Canflex maxmainsize:0.0)-allocatedsize); if (Totalflex > 0 | | crossaxisali Gnment = = crossaxisalignment.baseline) {Final double Spaceperflex = Canflex && totalflex > 0?  (Freespace/totalflex): Double.NaN;  Child = FirstChild;    while (child! = null) {final int flex = _getflex (child); if (Flex > 0) {final double maxchildextent = Canflex? (Child = = Lastflexchild?)      (freespace-allocatedflexspace): Spaceperflex * Flex): double.infinity;      Double minchildextent;          Switch (_getfit) {case FlexFit.tight:assert (Maxchildextent < double.infinity);          Minchildextent = maxchildextent;        Break          Case FlexFit.loose:minChildExtent = 0.0;      Break      } boxconstraints innerconstraints;            if (crossaxisalignment = = crossaxisalignment.stretch) {switch (_direction) {case Axis.horizontal: innerconstraints = new BoxconstrAints (Minwidth:minchildextent, Maxwidth:maxchildextent, MinHeight:constraints.maxHeight, Maxhe            Ight:constraints.maxHeight);          Break                                                  Case Axis.vertical:innerConstraints = new Boxconstraints (MinWidth:constraints.maxWidth, MaxWidth:constraints.maxWidth, Minheight:mi            Nchildextent, maxheight:maxchildextent);        Break }} else {switch (_direction) {case Axis.horizontal:innerConstraints = new Boxconstrain                                                  TS (minwidth:minchildextent, Maxwidth:maxchildextent,            MaxHeight:constraints.maxHeight);          Break CaSe Axis.vertical:innerConstraints = new boxconstraints (MaxWidth:constraints.maxWidth, Minheight:minchildextent, Maxheight:maxchilde            Xtent);        Break      }} child.layout (Innerconstraints, parentusessize:true);      Final double childsize = _getmainsize (child);      Allocatedsize + = Childsize;      Allocatedflexspace + = maxchildextent;    Crosssize = Math.max (crosssize, _getcrosssize (child)); } if (crossaxisalignment = = crossaxisalignment.baseline) {Final double distance = Child.getdistancetobaseline (Tex      Tbaseline, onlyreal:true);    if (distance! = null) Maxbaselinedistance = Math.max (maxbaselinedistance, distance);    } final Flexparentdata childparentdata = Child.parentdata;  Child = childparentdata.nextsibling; }}

The above code snippet also has two things to do:

    • Allocate the remaining space for a child that contains flex

For each flex space, it is calculated as follows:

final double freeSpace = math.max(0.0, (canFlex ? maxMainSize : 0.0) - allocatedSize);final double spacePerFlex = canFlex && totalFlex > 0 ? (freeSpace / totalFlex) : double.nan;

Where Allocatedsize is not included in the space occupied by flex. When the space occupied by each flex is calculated, the child containing flex is adjusted according to the setting of the cross axis.

    • Calculate the baseline value

If the intersection axis is aligned to baseline, the maximum baseline value is computed as the overall baseline value.

switch (_mainAxisAlignment) {  case MainAxisAlignment.start:    leadingSpace = 0.0;    betweenSpace = 0.0;    break;  case MainAxisAlignment.end:    leadingSpace = remainingSpace;    betweenSpace = 0.0;    break;  case MainAxisAlignment.center:    leadingSpace = remainingSpace / 2.0;    betweenSpace = 0.0;    break;  case MainAxisAlignment.spaceBetween:    leadingSpace = 0.0;    betweenSpace = totalChildren > 1 ? remainingSpace / (totalChildren - 1) : 0.0;    break;  case MainAxisAlignment.spaceAround:    betweenSpace = totalChildren > 0 ? remainingSpace / totalChildren : 0.0;    leadingSpace = betweenSpace / 2.0;    break;  case MainAxisAlignment.spaceEvenly:    betweenSpace = totalChildren > 0 ? remainingSpace / (totalChildren + 1) : 0.0;    leadingSpace = betweenSpace;    break;}

Then, the child in the spindle direction in accordance with the alignment of the setting, the position adjustment. The above code is the process of calculating the value of the blank area before and after, you can see the difference between Spacebetween, Spacearound and Spaceevenly.

Double childmainposition = Flipmainaxis? Actualsize-leadingspace:leadingspace;child = firstchild;while (child = null) {final Flexparentdata Childparentdata  = Child.parentdata;  Double childcrossposition;  Switch (_crossaxisalignment) {case CrossAxisAlignment.start:case CrossAxisAlignment.end:childCrossPosition = _startistopleft (Flipaxis (direction), textdirection, verticaldirection) = = (_crossaxisalignment = = Crossaxisalignment.start)?      0.0:crosssize-_getcrosssize (child);    Break      Case CrossAxisAlignment.center:childCrossPosition = crosssize/2.0-_getcrosssize (child)/2.0;    Break      Case CrossAxisAlignment.stretch:childCrossPosition = 0.0;    Break      Case CrossAxisAlignment.baseline:childCrossPosition = 0.0;        if (_direction = = axis.horizontal) {assert (Textbaseline! = null); Final double distance = Child.getdistancetobaseline (textbaseline, onlyreal:true);      if (distance! = null) childcrossposition = maxbaselinedistance-distance;  } break;  } if (Flipmainaxis) childmainposition-= _getmainsize (child); Switch (_direction) {Case Axis.horizontal:childParentData.offset = new offset (childmainposition, childcrossposit      ION);    Break      Case Axis.vertical:childParentData.offset = new offset (childcrossposition, childmainposition);  Break  } if (Flipmainaxis) {childmainposition-= Betweenspace;  } else {childmainposition + = _getmainsize (child) + betweenspace; } child = Childparentdata.nextsibling;}

Finally, based on the alignment settings of the intersection axis, the child is adjusted to position, and the layout ends.

We can go through the whole process:

    • Calculate the sum of Flex and find the last child with Flex set;
    • For a child that does not contain flex, the alignment is adjusted according to the intersection axis alignment, and the size of the area occupied by the spindle direction is calculated.
    • Calculates the space occupied by each flex and adjusts the child containing flex according to the cross-axis alignment;
    • If the intersection axis is set to baseline, the overall baseline value is calculated;
    • Adjust the child according to the spindle alignment;
    • Finally, according to the intersection axis alignment, all child positions are adjusted to complete the layout.
1.6 Usage Scenarios

Both row and column are very common layout controls. In general, for example, you can use a control when it is displayed in one row or column. It's not that you can use either row or column to layout, or stack to see the specific scene selection.

2. Column

When explaining the row, in fact, according to some of Flex's layout behavior, including source analysis, are also used in flex analysis. Both row and column are subclasses of Flex, except that the direction parameter is different. column is the same row, so there is no further explanation here.

When it comes to flex, it's also said to be referring to the flex layout of the Web, and if you have a relevant development experience, it's easier to understand how it's used and how it works.

3. Something

The author has built a flutter study related projects, GitHub address, which contains the author of the Flutter study related to some of the articles, will be updated regularly, will also upload some learning demo, welcome attention.

4. Reference
    1. Row class
    2. Column class
    3. mainaxisalignment enum
    4. crossaxisalignment enum
    5. Mainaxissize enum
    6. verticaldirection enum

Flutter layout (vii)-ROW, column detailed

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.