computeDryBaseline method

  1. @override
double? computeDryBaseline(
  1. covariant BoxConstraints constraints,
  2. TextBaseline baseline
)
override

Computes the value returned by getDryBaseline.

This method is for overriding only and shouldn't be called directly. To get this RenderBox's speculative baseline location for the given constraints, call getDryBaseline instead.

The "dry" in the method name means the implementation must not produce observable side effects when called. For example, it must not change the size of the RenderBox, or its children's paint offsets, otherwise that would results in UI changes when paint is called, or hit-testing behavior changes when hitTest is called. Moreover, accessing the current layout of this RenderBox or child RenderBoxes (including accessing size, or child.size) usually indicates a bug in the implementation, as the current layout is typically calculated using a set of BoxConstraints that's different from the constraints given as the first parameter. To get the size of this RenderBox or a child RenderBox in this method's implementation, use the getDryLayout method instead.

The implementation must return a value that represents the distance from the top of the box to the first baseline of the box's contents, for the given constraints, or null if the RenderBox has no baselines. It's the same exact value RenderBox.computeDistanceToActualBaseline would return, when this RenderBox was laid out at constraints in the same exact state.

Not all RenderBoxes support dry baseline computation. For example, to compute the dry baseline of a LayoutBuilder, its builder may have to be called with different constraints, which may have side effects such as updating the widget tree, violating the "dry" contract. In such cases the RenderBox must call debugCannotComputeDryLayout in an assert, and return a dummy baseline offset value (such as null).

Implementation

@override
double? computeDryBaseline(BoxConstraints constraints, TextBaseline baseline) {
  final _LayoutSizes sizes = _computeSizes(
    constraints: constraints,
    layoutChild: ChildLayoutHelper.dryLayoutChild,
    getBaseline: ChildLayoutHelper.getDryBaseline,
  );

  if (_isBaselineAligned) {
    return sizes.baselineOffset;
  }

  final BoxConstraints nonFlexConstraints = _constraintsForNonFlexChild(constraints);
  BoxConstraints constraintsForChild(RenderBox child) {
    final double? spacePerFlex = sizes.spacePerFlex;
    final int flex;
    return spacePerFlex != null && (flex = _getFlex(child)) > 0
      ? _constraintsForFlexChild(child, constraints, flex * spacePerFlex)
      : nonFlexConstraints;
  }

  BaselineOffset baselineOffset = BaselineOffset.noBaseline;
  switch (direction) {
    case Axis.vertical:
      final double freeSpace = math.max(0.0, sizes.mainAxisFreeSpace);
      final bool flipMainAxis = _flipMainAxis;
      final (double leadingSpaceY, double spaceBetween) = mainAxisAlignment._distributeSpace(freeSpace, childCount, flipMainAxis, spacing);
      double y = flipMainAxis
        ? leadingSpaceY + (childCount - 1) * spaceBetween + (sizes.axisSize.mainAxisExtent - sizes.mainAxisFreeSpace)
        : leadingSpaceY;
      final double directionUnit = flipMainAxis ? -1.0 : 1.0;
      for (RenderBox? child = firstChild; baselineOffset == BaselineOffset.noBaseline && child != null; child = childAfter(child)) {
        final BoxConstraints childConstraints = constraintsForChild(child);
        final Size childSize = child.getDryLayout(childConstraints);
        final double? childBaselineOffset = child.getDryBaseline(childConstraints, baseline);
        final double additionalY = flipMainAxis ? - childSize.height : 0.0;
        baselineOffset = BaselineOffset(childBaselineOffset) + y + additionalY;
        y += directionUnit * (spaceBetween + childSize.height);
      }
    case Axis.horizontal:
      final bool flipCrossAxis = _flipCrossAxis;
      for (RenderBox? child = firstChild; child != null; child = childAfter(child)) {
        final BoxConstraints childConstraints = constraintsForChild(child);
        final BaselineOffset distance = BaselineOffset(child.getDryBaseline(childConstraints, baseline));
        final double freeCrossAxisSpace = sizes.axisSize.crossAxisExtent - child.getDryLayout(childConstraints).height;
        final BaselineOffset childBaseline = distance + crossAxisAlignment._getChildCrossAxisOffset(freeCrossAxisSpace, flipCrossAxis);
        baselineOffset = baselineOffset.minOf(childBaseline);
      }
  }
  return baselineOffset.offset;
}