1. override
void performLayout()

Do the work of computing the layout for this render object.

Do not call this function directly: call layout instead. This function is called by layout when there is actually work to be done by this render object during layout. The layout constraints provided by your parent are available via the constraints getter.

If sizedByParent is true, then this function should not actually change the dimensions of this render object. Instead, that work should be done by performResize. If sizedByParent is false, then this function should both change the dimensions of this render object and instruct its children to layout.

In implementing this function, you must call layout on each of your children, passing true for parentUsesSize if your layout information is dependent on your child's layout information. Passing true for parentUsesSize ensures that this render object will undergo layout if the child undergoes layout. Otherwise, the child can changes its layout information without informing this render object.

Source

@override
void performLayout() {
  // Determine used flex factor, size inflexible items, calculate free space.
  int totalFlex = 0;
  int totalChildren = 0;
  assert(constraints != null);
  final double maxMainSize = _direction == Axis.horizontal ? constraints.maxWidth : constraints.maxHeight;
  final bool canFlex = maxMainSize < double.INFINITY;

  double crossSize = 0.0;
  double allocatedSize = 0.0; // Sum of the sizes of the the non-flexible children.
  RenderBox child = firstChild;
  while (child != null) {
    final FlexParentData childParentData = child.parentData;
    totalChildren++;
    final int flex = _getFlex(child);
    if (flex > 0) {
      assert(() {
        final String identity = _direction == Axis.horizontal ? 'row' : 'column';
        final String axis = _direction == Axis.horizontal ? 'horizontal' : 'vertical';
        final String dimension = _direction == Axis.horizontal ? 'width' : 'height';
        String error, message;
        String addendum = '';
        if (maxMainSize == double.INFINITY) {
          error = 'RenderFlex children have non-zero flex but incoming $dimension constraints are unbounded.';
          message = 'When a $identity is in a parent that does not provide a finite $dimension constraint, for example '
                    'if it is in a $axis scrollable, it will try to shrink-wrap its children along the $axis '
                    'axis. Setting a flex on a child (e.g. using a Flexible) indicates that the child is to '
                    'expand to fill the remaining space in the $axis direction.';
          StringBuffer information = new StringBuffer();
          RenderBox node = this;
          switch (_direction) {
            case Axis.horizontal:
              while (!node.constraints.hasBoundedWidth && node.parent is RenderBox)
                node = node.parent;
              if (!node.constraints.hasBoundedWidth)
                node = null;
              break;
            case Axis.vertical:
              while (!node.constraints.hasBoundedHeight && node.parent is RenderBox)
                node = node.parent;
              if (!node.constraints.hasBoundedHeight)
                node = null;
              break;
          }
          if (node != null) {
            information.writeln('The nearest ancestor providing an unbounded width constraint is:');
            information.writeln('  $node');
            List<String> description = <String>[];
            node.debugFillDescription(description);
            for (String line in description)
              information.writeln('  $line');
          }
          information.writeln('See also: https://flutter.io/layout/');
          addendum = information.toString();
        } else {
          return true;
        }
        throw new FlutterError(
          '$error\n'
          '$message\n'
          'These two directives are mutually exclusive. If a parent is to shrink-wrap its child, the child '
          'cannot simultaneously expand to fit its parent.\n'
          'The affected RenderFlex is:\n'
          '  $this\n'
          'The creator information is set to:\n'
          '  $debugCreator\n'
          '$addendum'
          'If this message did not help you determine the problem, consider using debugDumpRenderTree():\n'
          '  https://flutter.io/debugging/#rendering-layer\n'
          '  http://docs.flutter.io/flutter/rendering/debugDumpRenderTree.html\n'
          'If none of the above helps enough to fix this problem, please don\'t hesitate to file a bug:\n'
          '  https://github.com/flutter/flutter/issues/new'
        );
      });
      totalFlex += childParentData.flex;
    } 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));
    }
    assert(child.parentData == childParentData);
    child = childParentData.nextSibling;
  }
  _overflow = math.max(0.0, allocatedSize - (canFlex ? maxMainSize : 0.0));

  // Distribute free space to flexible children, and determine baseline.
  final double freeSpace = math.max(0.0, (canFlex ? maxMainSize : 0.0) - allocatedSize);
  double maxBaselineDistance = 0.0;
  if (totalFlex > 0 || crossAxisAlignment == CrossAxisAlignment.baseline) {
    final double spacePerFlex = totalFlex > 0 ? (freeSpace / totalFlex) : 0.0;
    child = firstChild;
    while (child != null) {
      final int flex = _getFlex(child);
      if (flex > 0) {
        final double maxChildExtent = spacePerFlex * flex;
        double minChildExtent;
        switch (_getFit(child)) {
          case FlexFit.tight:
            minChildExtent = maxChildExtent;
            break;
          case FlexFit.loose:
            minChildExtent = 0.0;
            break;
        }
        assert(minChildExtent != null);
        BoxConstraints innerConstraints;
        if (crossAxisAlignment == CrossAxisAlignment.stretch) {
          switch (_direction) {
            case Axis.horizontal:
              innerConstraints = new BoxConstraints(minWidth: minChildExtent,
                                                    maxWidth: maxChildExtent,
                                                    minHeight: constraints.maxHeight,
                                                    maxHeight: constraints.maxHeight);
              break;
            case Axis.vertical:
              innerConstraints = new BoxConstraints(minWidth: constraints.maxWidth,
                                                    maxWidth: constraints.maxWidth,
                                                    minHeight: minChildExtent,
                                                    maxHeight: maxChildExtent);
              break;
          }
        } else {
          switch (_direction) {
            case Axis.horizontal:
              innerConstraints = new BoxConstraints(minWidth: minChildExtent,
                                                    maxWidth: maxChildExtent,
                                                    maxHeight: constraints.maxHeight);
              break;
            case Axis.vertical:
              innerConstraints = new BoxConstraints(maxWidth: constraints.maxWidth,
                                                    minHeight: minChildExtent,
                                                    maxHeight: maxChildExtent);
              break;
          }
        }
        child.layout(innerConstraints, parentUsesSize: true);
        allocatedSize += _getMainSize(child);
        crossSize = math.max(crossSize, _getCrossSize(child));
      }
      if (crossAxisAlignment == CrossAxisAlignment.baseline) {
        assert(() {
          if (textBaseline == null)
            throw new FlutterError('To use FlexAlignItems.baseline, you must also specify which baseline to use using the "baseline" argument.');
          return true;
        });
        double distance = child.getDistanceToBaseline(textBaseline, onlyReal: true);
        if (distance != null)
          maxBaselineDistance = math.max(maxBaselineDistance, distance);
      }
      final FlexParentData childParentData = child.parentData;
      child = childParentData.nextSibling;
    }
  }

  // Align items along the main axis.
  double leadingSpace;
  double betweenSpace;
  double remainingSpace;
  if (canFlex) {
    final bool isMainAxisSizeMax = mainAxisSize == MainAxisSize.max;
    final double preferredSize = isMainAxisSizeMax ? maxMainSize : allocatedSize;
    switch (_direction) {
      case Axis.horizontal:
        size = constraints.constrain(new Size(preferredSize, crossSize));
        remainingSpace = math.max(0.0, size.width - allocatedSize);
        crossSize = size.height;
        assert(isMainAxisSizeMax ? size.width == maxMainSize : size.width >= constraints.minWidth);
        break;
      case Axis.vertical:
        size = constraints.constrain(new Size(crossSize, preferredSize));
        remainingSpace = math.max(0.0, size.height - allocatedSize);
        crossSize = size.width;
        assert(isMainAxisSizeMax ? size.height == maxMainSize : size.height >= constraints.minHeight);
        break;
    }
  } else {
    leadingSpace = 0.0;
    betweenSpace = 0.0;
    switch (_direction) {
      case Axis.horizontal:
        size = constraints.constrain(new Size(_overflow, crossSize));
        crossSize = size.height;
        remainingSpace = math.max(0.0, size.width - _overflow);
        break;
      case Axis.vertical:
        size = constraints.constrain(new Size(crossSize, _overflow));
        crossSize = size.width;
        remainingSpace = math.max(0.0, size.height - _overflow);
        break;
    }
    _overflow = 0.0;
  }
  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;
  }

  // Position elements
  double childMainPosition = leadingSpace;
  child = firstChild;
  while (child != null) {
    final FlexParentData childParentData = child.parentData;
    double childCrossPosition;
    switch (_crossAxisAlignment) {
      case CrossAxisAlignment.stretch:
      case CrossAxisAlignment.start:
        childCrossPosition = 0.0;
        break;
      case CrossAxisAlignment.end:
        childCrossPosition = crossSize - _getCrossSize(child);
        break;
      case CrossAxisAlignment.center:
        childCrossPosition = crossSize / 2.0 - _getCrossSize(child) / 2.0;
        break;
      case CrossAxisAlignment.baseline:
        childCrossPosition = 0.0;
        if (_direction == Axis.horizontal) {
          assert(textBaseline != null);
          double distance = child.getDistanceToBaseline(textBaseline, onlyReal: true);
          if (distance != null)
            childCrossPosition = maxBaselineDistance - distance;
        }
        break;
    }
    switch (_direction) {
      case Axis.horizontal:
        childParentData.offset = new Offset(childMainPosition, childCrossPosition);
        break;
      case Axis.vertical:
        childParentData.offset = new Offset(childCrossPosition, childMainPosition);
        break;
    }
    childMainPosition += _getMainSize(child) + betweenSpace;
    child = childParentData.nextSibling;
  }
}