Fluent layout - Row, Android framework video

Keywords: html5 Design Pattern css Programmer Flutter

A multi child node control, which is very common in fluent, arranges children in a row. It is estimated that the Flex layout in the Web is used for reference, so many properties and performance are similar to it. Note, however, that it does not have a scrolling attribute. If it exceeds one line, an overflow prompt will be displayed under debug.

1.2 layout behavior

The layout of Row has six steps. The layout performance comes from Flex (the parent class of Row and Column):

  1. First, the child whose flex is null or 0 is arranged according to the unrestricted main axis constraint, and then the child is adjusted according to the cross axis constraint;
  2. Divide the remaining space in the spindle direction into corresponding equal parts according to the non empty flex value;
  3. Adjust the child whose flex value is not empty in the above step in the cross axis direction, and use the maximum constraint condition in the spindle direction to make it occupy the space allocated in step 2;
  4. The range of Flex cross axis is taken from the maximum cross axis of the child node;
  5. The value of spindle Flex is determined by the mainaxissize attribute, where the mainaxissize can take max, min and specific value values;
  6. The location of each child is determined by mainAxisAlignment and crossAxisAlignment.

On the surface, the Row layout behavior has so many steps. In fact, it is still simple. You can fully refer to the Flex layout in the web, including the concepts of spindle and cross axis.

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-72comvow-163121126115)( https://user-gold-cdn.xitu.io/2018/8/2/164f7c062937c43b?imageView2/0/w/1280/h/960/ignore -error/1)]

1.3 inheritance

Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > MultiChildRenderObjectWidget > Flex > Row 

Row and Column are subclasses of Flex, and their specific implementation is also completed by Flex, but the parameters are different.

1.4 example 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,
    ),
  ],
) 

For a very simple example, use the Expanded control to divide the width of a row into four equal parts. The first and third children account for 1 / 4 of the area, and the second child accounts for 1 / 2 of the area, which is controlled by the flex attribute.

1.5 source code analysis

The constructor is 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 resolution

MainAxisAlignment: the alignment in the spindle direction will affect the position of the child. The default is start.

Where the MainAxisAlignment enumeration value:

  • Center: place the children in the center of the spindle;
  • End: place children at the end of the spindle;
  • spaceAround: divide the blank areas in the main axis direction equally so that the blank areas between children are equal, but the blank areas of the first and last children are 1 / 2;
  • spaceBetween: divide the blank areas in the main axis direction equally, so that the blank areas between children are equal, and the head and tail children are close to the head and tail without gap;
  • Spaceevery: divide the blank areas in the main axis direction equally so that the blank areas between children are equal, including the first and last children;
  • start: place the children at the starting point of the spindle;

The difference among spaceAround, spaceBetween and spaceevery is the way to treat the first and last child ren. The distance from the head to the tail is 1 / 2, 0 and 1 of the blank area respectively.

MainAxisSize: the value that occupies space in the spindle direction. The default value is max.

There are two values for MainAxisSize:

  • max: maximize the available space in the spindle direction according to the incoming layout constraints;
  • min: opposite to max, it minimizes the available space in the spindle direction;

CrossAxisAlignment: the alignment of children in the cross axis direction is slightly different from that of MainAxisAlignment.

CrossAxisAlignment enumeration values are as follows:

  • baseline: align the baselines of children in the cross axis direction;
  • Center: children are displayed in the center on the cross axis;
  • End: children are displayed at the end of the cross axis;
  • start: children are displayed at the starting point on the cross axis;
  • stretch: let children fill the cross axis direction;

TextDirection: compatible setting of Arabic system. Generally, it does not need to be processed.

VerticalDirection: defines the placement order of children. The default is down.

There are two kinds of VerticalDirection enumeration values:

  • down: layout from top to bottom;
  • up: layout from bottom to top.

If top corresponds to Row and Column, it is the left and top. If bottom, it is the right and bottom.

TextBaseline: there are two ways to use TextBaseline, which have been introduced earlier.

1.5.2 source code

The source code of Row and Column is a constructor, and the specific implementation is all in their parent class Flex.

About 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>[],
}) 

It can be seen that the constructor of Flex has one more parameter than that of Row and Column. The difference between Row and Column is the difference of this direction parameter. When it is Axis.horizontal, it is Row; when it is Axis.vertical, it is Column.

Let's take a look at the layout functions of Flex. Since there are many layout functions, we will explain them in sections:

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:
          innerConstraints = new BoxConstraints(minHeight: constraints.maxHeight,
                                                maxHeight: 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(maxHeight: 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;
} 

In the above code, I have eliminated some assert and error messages in the middle, which does not affect the actual understanding.

At the beginning of the layout, the child will be traversed first. The traversal has two functions:

  • For children with flex value, calculate the sum of flex and find the last child containing flex value. The reason for finding this child is that the spindle alignment may be adjusted, so you need to find it;
  • For a child without flex, adjust the child according to the setting of the cross axis direction.
final double freeSpace = math.max(0.0, (canFlex ? maxMainSize : 0.0) - allocatedSize);
if (totalFlex > 0 || crossAxisAlignment == 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;


#### [attachment] relevant structure and data

**[CodeChina Open source projects:< Android Summary of study notes+Mobile architecture video+Real interview questions for large factories+Project practice source code](

)**

> **Source code, notes, videos. senior UI,Performance optimization, architect courses NDK,Hybrid development( ReactNative+Weex)Wechat applet Flutter Comprehensive Android Advanced practice technology, discuss and solve problems with technical Daniel.**

![image](https://img-blog.csdnimg.cn/img_convert/6033debfe8a45b58eb758d9e59025df5.png)



> **This article has been[tencent CODING Open source hosting project:< Android Summary of study notes+Mobile architecture video+Real interview questions for large factories+Project practice source code](https://ali1024.coding.net/public/P7/Android/git), self-study resources and series of articles are constantly updated**
roid Advanced practice technology, discuss and solve problems with technical Daniel.**

[External chain picture transfer...(img-3EftMxfO-1631251126117)]



> **This article has been[tencent CODING Open source hosting project:< Android Summary of study notes+Mobile architecture video+Real interview questions for large factories+Project practice source code](https://ali1024.coding.net/public/P7/Android/git), self-study resources and series of articles are constantly updated**

Posted by Ruud Hermans on Sat, 20 Nov 2021 04:21:52 -0800