performLayout method

  1. @override
void performLayout ()
override

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 change its layout information without informing this render object.

Implementation

@override
void performLayout() {
  assert(() {
    switch (mainAxis) {
      case Axis.horizontal:
        if (!constraints.hasBoundedWidth)
          return true;
        break;
      case Axis.vertical:
        if (!constraints.hasBoundedHeight)
          return true;
        break;
    }
    throw FlutterError(
      'RenderListBody must have unlimited space along its main axis.\n'
      'RenderListBody does not clip or resize its children, so it must be '
      'placed in a parent that does not constrain the main '
      'axis. You probably want to put the RenderListBody inside a '
      'RenderViewport with a matching main axis.'
    );
  }());
  assert(() {
    switch (mainAxis) {
      case Axis.horizontal:
        if (constraints.hasBoundedHeight)
          return true;
        break;
      case Axis.vertical:
        if (constraints.hasBoundedWidth)
          return true;
        break;
    }
    // TODO(ianh): Detect if we're actually nested blocks and say something
    // more specific to the exact situation in that case, and don't mention
    // nesting blocks in the negative case.
    throw FlutterError(
      'RenderListBody must have a bounded constraint for its cross axis.\n'
      'RenderListBody forces its children to expand to fit the RenderListBody\'s container, '
      'so it must be placed in a parent that constrains the cross '
      'axis to a finite dimension. If you are attempting to nest a RenderListBody with '
      'one direction inside one of another direction, you will want to '
      'wrap the inner one inside a box that fixes the dimension in that direction, '
      'for example, a RenderIntrinsicWidth or RenderIntrinsicHeight object. '
      'This is relatively expensive, however.' // (that's why we don't do it automatically)
    );
  }());
  double mainAxisExtent = 0.0;
  RenderBox child = firstChild;
  switch (axisDirection) {
  case AxisDirection.right:
    final BoxConstraints innerConstraints = BoxConstraints.tightFor(height: constraints.maxHeight);
    while (child != null) {
      child.layout(innerConstraints, parentUsesSize: true);
      final ListBodyParentData childParentData = child.parentData;
      childParentData.offset = Offset(mainAxisExtent, 0.0);
      mainAxisExtent += child.size.width;
      assert(child.parentData == childParentData);
      child = childParentData.nextSibling;
    }
    size = constraints.constrain(Size(mainAxisExtent, constraints.maxHeight));
    break;
  case AxisDirection.left:
    final BoxConstraints innerConstraints = BoxConstraints.tightFor(height: constraints.maxHeight);
    while (child != null) {
      child.layout(innerConstraints, parentUsesSize: true);
      final ListBodyParentData childParentData = child.parentData;
      mainAxisExtent += child.size.width;
      assert(child.parentData == childParentData);
      child = childParentData.nextSibling;
    }
    double position = 0.0;
    child = firstChild;
    while (child != null) {
      final ListBodyParentData childParentData = child.parentData;
      position += child.size.width;
      childParentData.offset = Offset(mainAxisExtent - position, 0.0);
      assert(child.parentData == childParentData);
      child = childParentData.nextSibling;
    }
    size = constraints.constrain(Size(mainAxisExtent, constraints.maxHeight));
    break;
  case AxisDirection.down:
    final BoxConstraints innerConstraints = BoxConstraints.tightFor(width: constraints.maxWidth);
    while (child != null) {
      child.layout(innerConstraints, parentUsesSize: true);
      final ListBodyParentData childParentData = child.parentData;
      childParentData.offset = Offset(0.0, mainAxisExtent);
      mainAxisExtent += child.size.height;
      assert(child.parentData == childParentData);
      child = childParentData.nextSibling;
    }
    size = constraints.constrain(Size(constraints.maxWidth, mainAxisExtent));
    break;
  case AxisDirection.up:
    final BoxConstraints innerConstraints = BoxConstraints.tightFor(width: constraints.maxWidth);
    while (child != null) {
      child.layout(innerConstraints, parentUsesSize: true);
      final ListBodyParentData childParentData = child.parentData;
      mainAxisExtent += child.size.height;
      assert(child.parentData == childParentData);
      child = childParentData.nextSibling;
    }
    double position = 0.0;
    child = firstChild;
    while (child != null) {
      final ListBodyParentData childParentData = child.parentData;
      position += child.size.height;
      childParentData.offset = Offset(0.0, mainAxisExtent - position);
      assert(child.parentData == childParentData);
      child = childParentData.nextSibling;
    }
    size = constraints.constrain(Size(constraints.maxWidth, mainAxisExtent));
    break;
  }
  assert(size.isFinite);
}