computeDryBaseline method
- covariant BoxConstraints constraints,
- TextBaseline baseline
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;
}