performBoxLayout method

  1. @override
void performBoxLayout(
  1. BoxConstraints constraints
)
override

Perform layout with typed box constraints

Subclasses override this instead of performLayout. The default implementation sizes to the maxima, treating an unbounded axis as the corresponding lower bound.

Implementation

@override
void performBoxLayout(BoxConstraints constraints) {
  final boxes = children.whereType<RenderBox>().toList(growable: false);
  var naturalWidth = 0;
  var naturalHeight = 0;
  var hasNonPositionedChild = false;
  final loose = BoxConstraints.loose(
    maxWidth: constraints.maxWidth,
    maxHeight: constraints.maxHeight,
  );

  for (final child in boxes) {
    final data = _childData[child] ?? const StackChildData();
    if (data.isPositioned) continue;
    hasNonPositionedChild = true;
    final childConstraints = _fit == StackFit.expand
        ? BoxConstraints.expand(
            width: constraints.maxWidth,
            height: constraints.maxHeight,
          )
        : loose;
    child.layout(childConstraints);
    if (child.size.width > naturalWidth) naturalWidth = child.size.width;
    if (child.size.height > naturalHeight) naturalHeight = child.size.height;
  }

  if (!hasNonPositionedChild &&
      (constraints.maxWidth == null || constraints.maxHeight == null)) {
    for (final child in boxes) {
      final data = _childData[child] ?? const StackChildData();
      child.layout(
        _positionedConstraints(
          data,
          width: constraints.maxWidth,
          height: constraints.maxHeight,
        ),
      );
      naturalWidth = math.max(
        naturalWidth,
        _positionedExtent(child.size.width, data.left, data.right),
      );
      naturalHeight = math.max(
        naturalHeight,
        _positionedExtent(child.size.height, data.top, data.bottom),
      );
    }
  }

  final fillAvailable = _fit == StackFit.expand || !hasNonPositionedChild;
  size = Size(
    constraints.constrainWidth(
      fillAvailable ? constraints.maxWidth ?? naturalWidth : naturalWidth,
    ),
    constraints.constrainHeight(
      fillAvailable ? constraints.maxHeight ?? naturalHeight : naturalHeight,
    ),
  );

  for (final child in boxes) {
    final data = _childData[child] ?? const StackChildData();
    if (!data.isPositioned) {
      final offset = _alignedOffset(
        _alignment,
        Offset(
          size.width - child.size.width,
          size.height - child.size.height,
        ),
      );
      positionChild(child, offset.dx, offset.dy);
      continue;
    }

    child.layout(
      _positionedConstraints(data, width: size.width, height: size.height),
    );
    final aligned = _alignedOffset(
      _alignment,
      Offset(size.width - child.size.width, size.height - child.size.height),
    );
    final x =
        data.left ??
        (data.right == null
            ? aligned.dx
            : size.width - data.right! - child.size.width);
    final y =
        data.top ??
        (data.bottom == null
            ? aligned.dy
            : size.height - data.bottom! - child.size.height);
    positionChild(child, x, y);
  }
}