mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
_RenderDecorator.computeDryBaseline
(#146365)
Depends on https://github.com/flutter/flutter/pull/146363 No test because the consistency of the `computeDryBaseline` implementations is checked at paint time.
This commit is contained in:
parent
21da3a8063
commit
f76eda1e7f
@ -697,12 +697,14 @@ class _Decoration {
|
|||||||
// all of the renderer children of a _RenderDecoration.
|
// all of the renderer children of a _RenderDecoration.
|
||||||
class _RenderDecorationLayout {
|
class _RenderDecorationLayout {
|
||||||
const _RenderDecorationLayout({
|
const _RenderDecorationLayout({
|
||||||
|
required this.inputConstraints,
|
||||||
required this.baseline,
|
required this.baseline,
|
||||||
required this.containerHeight,
|
required this.containerHeight,
|
||||||
required this.subtextSize,
|
required this.subtextSize,
|
||||||
required this.size,
|
required this.size,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
final BoxConstraints inputConstraints;
|
||||||
final double baseline;
|
final double baseline;
|
||||||
final double containerHeight;
|
final double containerHeight;
|
||||||
final _SubtextSize? subtextSize;
|
final _SubtextSize? subtextSize;
|
||||||
@ -903,6 +905,10 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin
|
|||||||
static double _getBaseline(RenderBox box, BoxConstraints boxConstraints) {
|
static double _getBaseline(RenderBox box, BoxConstraints boxConstraints) {
|
||||||
return ChildLayoutHelper.getBaseline(box, boxConstraints, TextBaseline.alphabetic) ?? box.size.height;
|
return ChildLayoutHelper.getBaseline(box, boxConstraints, TextBaseline.alphabetic) ?? box.size.height;
|
||||||
}
|
}
|
||||||
|
static double _getDryBaseline(RenderBox box, BoxConstraints boxConstraints) {
|
||||||
|
return ChildLayoutHelper.getDryBaseline(box, boxConstraints, TextBaseline.alphabetic)
|
||||||
|
?? ChildLayoutHelper.dryLayoutChild(box, boxConstraints).height;
|
||||||
|
}
|
||||||
|
|
||||||
static BoxParentData _boxParentData(RenderBox box) => box.parentData! as BoxParentData;
|
static BoxParentData _boxParentData(RenderBox box) => box.parentData! as BoxParentData;
|
||||||
|
|
||||||
@ -943,7 +949,11 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin
|
|||||||
// Returns a value used by performLayout to position all of the renderers.
|
// Returns a value used by performLayout to position all of the renderers.
|
||||||
// This method applies layout to all of the renderers except the container.
|
// This method applies layout to all of the renderers except the container.
|
||||||
// For convenience, the container is laid out in performLayout().
|
// For convenience, the container is laid out in performLayout().
|
||||||
_RenderDecorationLayout _layout(BoxConstraints constraints) {
|
_RenderDecorationLayout _layout(
|
||||||
|
BoxConstraints constraints, {
|
||||||
|
required ChildLayouter layoutChild,
|
||||||
|
required _ChildBaselineGetter getBaseline,
|
||||||
|
}) {
|
||||||
assert(
|
assert(
|
||||||
constraints.maxWidth < double.infinity,
|
constraints.maxWidth < double.infinity,
|
||||||
'An InputDecorator, which is typically created by a TextField, cannot '
|
'An InputDecorator, which is typically created by a TextField, cannot '
|
||||||
@ -958,7 +968,8 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin
|
|||||||
final BoxConstraints boxConstraints = constraints.loosen();
|
final BoxConstraints boxConstraints = constraints.loosen();
|
||||||
|
|
||||||
// Layout all the widgets used by InputDecorator
|
// Layout all the widgets used by InputDecorator
|
||||||
final double iconWidth = (icon?..layout(boxConstraints, parentUsesSize: true))?.size.width ?? 0.0;
|
final RenderBox? icon = this.icon;
|
||||||
|
final double iconWidth = icon == null ? 0.0 : layoutChild(icon, boxConstraints).width;
|
||||||
final BoxConstraints containerConstraints = boxConstraints.deflate(EdgeInsets.only(left: iconWidth));
|
final BoxConstraints containerConstraints = boxConstraints.deflate(EdgeInsets.only(left: iconWidth));
|
||||||
final BoxConstraints contentConstraints = containerConstraints.deflate(EdgeInsets.only(left: contentPadding.horizontal));
|
final BoxConstraints contentConstraints = containerConstraints.deflate(EdgeInsets.only(left: contentPadding.horizontal));
|
||||||
|
|
||||||
@ -966,26 +977,27 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin
|
|||||||
// occupied by the icon and counter.
|
// occupied by the icon and counter.
|
||||||
final _SubtextSize? subtextSize = _computeSubtextSizes(
|
final _SubtextSize? subtextSize = _computeSubtextSizes(
|
||||||
constraints: contentConstraints,
|
constraints: contentConstraints,
|
||||||
layoutChild: ChildLayoutHelper.layoutChild,
|
layoutChild: layoutChild,
|
||||||
getBaseline: _getBaseline,
|
getBaseline: getBaseline,
|
||||||
);
|
);
|
||||||
|
|
||||||
final RenderBox? prefixIcon = this.prefixIcon;
|
final RenderBox? prefixIcon = this.prefixIcon;
|
||||||
final RenderBox? suffixIcon = this.suffixIcon;
|
final RenderBox? suffixIcon = this.suffixIcon;
|
||||||
final Size prefixIconSize = (prefixIcon?..layout(containerConstraints, parentUsesSize: true))?.size ?? Size.zero;
|
final Size prefixIconSize = prefixIcon == null ? Size.zero : layoutChild(prefixIcon, containerConstraints);
|
||||||
final Size suffixIconSize = (suffixIcon?..layout(containerConstraints, parentUsesSize: true))?.size ?? Size.zero;
|
final Size suffixIconSize = suffixIcon == null ? Size.zero : layoutChild(suffixIcon, containerConstraints);
|
||||||
final RenderBox? prefix = this.prefix;
|
final RenderBox? prefix = this.prefix;
|
||||||
final RenderBox? suffix = this.suffix;
|
final RenderBox? suffix = this.suffix;
|
||||||
final Size prefixSize = (prefix?..layout(contentConstraints, parentUsesSize: true))?.size ?? Size.zero;
|
final Size prefixSize = prefix == null ? Size.zero : layoutChild(prefix, contentConstraints);
|
||||||
final Size suffixSize = (suffix?..layout(contentConstraints, parentUsesSize: true))?.size ?? Size.zero;
|
final Size suffixSize = suffix == null ? Size.zero : layoutChild(suffix, contentConstraints);
|
||||||
|
|
||||||
final EdgeInsetsDirectional accessoryHorizontalInsets = EdgeInsetsDirectional.only(
|
final EdgeInsetsDirectional accessoryHorizontalInsets = EdgeInsetsDirectional.only(
|
||||||
start: iconWidth + prefixSize.width + (prefixIcon == null ? contentPadding.start : prefixIcon.size.width),
|
start: iconWidth + prefixSize.width + (prefixIcon == null ? contentPadding.start : prefixIconSize.width),
|
||||||
end: suffixSize.width + (suffixIcon == null ? contentPadding.end : suffixIcon.size.width),
|
end: suffixSize.width + (suffixIcon == null ? contentPadding.end : suffixIconSize.width),
|
||||||
);
|
);
|
||||||
|
|
||||||
final double inputWidth = math.max(0.0, constraints.maxWidth - accessoryHorizontalInsets.horizontal);
|
final double inputWidth = math.max(0.0, constraints.maxWidth - accessoryHorizontalInsets.horizontal);
|
||||||
final RenderBox? label = this.label;
|
final RenderBox? label = this.label;
|
||||||
|
final double topHeight;
|
||||||
if (label != null) {
|
if (label != null) {
|
||||||
final double suffixIconSpace = decoration.border.isOutline
|
final double suffixIconSpace = decoration.border.isOutline
|
||||||
? lerpDouble(suffixIconSize.width, 0.0, decoration.floatingLabelProgress)!
|
? lerpDouble(suffixIconSize.width, 0.0, decoration.floatingLabelProgress)!
|
||||||
@ -995,18 +1007,21 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin
|
|||||||
constraints.maxWidth - (iconWidth + contentPadding.horizontal + prefixIconSize.width + suffixIconSpace),
|
constraints.maxWidth - (iconWidth + contentPadding.horizontal + prefixIconSize.width + suffixIconSpace),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Increase the available width for the label when it is scaled down.
|
// Increase the available width for the label when it is scaled down.
|
||||||
final double invertedLabelScale = lerpDouble(1.00, 1 / _kFinalLabelScale, decoration.floatingLabelProgress)!;
|
final double invertedLabelScale = lerpDouble(1.00, 1 / _kFinalLabelScale, decoration.floatingLabelProgress)!;
|
||||||
final BoxConstraints labelConstraints = boxConstraints.copyWith(maxWidth: labelWidth * invertedLabelScale);
|
final BoxConstraints labelConstraints = boxConstraints.copyWith(maxWidth: labelWidth * invertedLabelScale);
|
||||||
label.layout(labelConstraints, parentUsesSize: true);
|
layoutChild(label, labelConstraints);
|
||||||
|
|
||||||
|
final double labelHeight = decoration.floatingLabelHeight;
|
||||||
|
topHeight = decoration.border.isOutline
|
||||||
|
? math.max(labelHeight - getBaseline(label, labelConstraints), 0.0)
|
||||||
|
: labelHeight;
|
||||||
|
} else {
|
||||||
|
topHeight = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The height of the input needs to accommodate label above and counter and
|
// The height of the input needs to accommodate label above and counter and
|
||||||
// helperError below, when they exist.
|
// helperError below, when they exist.
|
||||||
final double labelHeight = label == null ? 0 : decoration.floatingLabelHeight;
|
|
||||||
final double topHeight = decoration.border.isOutline
|
|
||||||
? math.max(labelHeight - (label?.getDistanceToBaseline(TextBaseline.alphabetic) ?? 0.0), 0.0)
|
|
||||||
: labelHeight;
|
|
||||||
final double bottomHeight = subtextSize?.bottomHeight ?? 0.0;
|
final double bottomHeight = subtextSize?.bottomHeight ?? 0.0;
|
||||||
final Offset densityOffset = decoration.visualDensity.baseSizeAdjustment;
|
final Offset densityOffset = decoration.visualDensity.baseSizeAdjustment;
|
||||||
final BoxConstraints inputConstraints = boxConstraints
|
final BoxConstraints inputConstraints = boxConstraints
|
||||||
@ -1015,17 +1030,18 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin
|
|||||||
|
|
||||||
final RenderBox? input = this.input;
|
final RenderBox? input = this.input;
|
||||||
final RenderBox? hint = this.hint;
|
final RenderBox? hint = this.hint;
|
||||||
final Size inputSize = (input?..layout(inputConstraints, parentUsesSize: true))?.size ?? Size.zero;
|
final Size inputSize = input == null ? Size.zero : layoutChild(input, inputConstraints);
|
||||||
final Size hintSize = (hint?..layout(boxConstraints.tighten(width: inputWidth), parentUsesSize: true))?.size ?? Size.zero;
|
final Size hintSize = hint == null ? Size.zero : layoutChild(hint, boxConstraints.tighten(width: inputWidth));
|
||||||
final double inputBaseline = input == null ? 0.0 : _getBaseline(input, inputConstraints);
|
final double inputBaseline = input == null ? 0.0 : getBaseline(input, inputConstraints);
|
||||||
final double hintBaseline = hint == null ? 0.0 : _getBaseline(hint, boxConstraints.tighten(width: inputWidth));
|
final double hintBaseline = hint == null ? 0.0 : getBaseline(hint, boxConstraints.tighten(width: inputWidth));
|
||||||
|
|
||||||
// The field can be occupied by a hint or by the input itself
|
// The field can be occupied by a hint or by the input itself
|
||||||
final double inputHeight = math.max(hintSize.height, inputSize.height);
|
final double inputHeight = math.max(hintSize.height, inputSize.height);
|
||||||
final double inputInternalBaseline = math.max(inputBaseline, hintBaseline);
|
final double inputInternalBaseline = math.max(inputBaseline, hintBaseline);
|
||||||
|
|
||||||
final double prefixBaseline = prefix == null ? 0.0 : _getBaseline(prefix, contentConstraints);
|
final double prefixBaseline = prefix == null ? 0.0 : getBaseline(prefix, contentConstraints);
|
||||||
final double suffixBaseline = suffix == null ? 0.0 : _getBaseline(suffix, contentConstraints);
|
final double suffixBaseline = suffix == null ? 0.0 : getBaseline(suffix, contentConstraints);
|
||||||
|
|
||||||
// Calculate the amount that prefix/suffix affects height above and below
|
// Calculate the amount that prefix/suffix affects height above and below
|
||||||
// the input.
|
// the input.
|
||||||
final double fixHeight = math.max(prefixBaseline, suffixBaseline);
|
final double fixHeight = math.max(prefixBaseline, suffixBaseline);
|
||||||
@ -1117,6 +1133,7 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin
|
|||||||
}
|
}
|
||||||
|
|
||||||
return _RenderDecorationLayout(
|
return _RenderDecorationLayout(
|
||||||
|
inputConstraints: inputConstraints,
|
||||||
containerHeight: containerHeight,
|
containerHeight: containerHeight,
|
||||||
baseline: baseline,
|
baseline: baseline,
|
||||||
subtextSize: subtextSize,
|
subtextSize: subtextSize,
|
||||||
@ -1237,27 +1254,51 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin
|
|||||||
@override
|
@override
|
||||||
double computeDistanceToActualBaseline(TextBaseline baseline) {
|
double computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||||
final RenderBox? input = this.input;
|
final RenderBox? input = this.input;
|
||||||
return input == null
|
if (input == null) {
|
||||||
? 0.0
|
return 0.0;
|
||||||
: _boxParentData(input).offset.dy + (input.getDistanceToActualBaseline(baseline) ?? 0.0);
|
}
|
||||||
|
return _boxParentData(input).offset.dy + (input.getDistanceToActualBaseline(baseline) ?? input.size.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Records where the label was painted.
|
// Records where the label was painted.
|
||||||
Matrix4? _labelTransform;
|
Matrix4? _labelTransform;
|
||||||
|
|
||||||
|
@override
|
||||||
|
double? computeDryBaseline(covariant BoxConstraints constraints, TextBaseline baseline) {
|
||||||
|
final RenderBox? input = this.input;
|
||||||
|
if (input == null) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
final _RenderDecorationLayout layout = _layout(
|
||||||
|
constraints,
|
||||||
|
layoutChild: ChildLayoutHelper.dryLayoutChild,
|
||||||
|
getBaseline: _getDryBaseline,
|
||||||
|
);
|
||||||
|
return switch (baseline) {
|
||||||
|
TextBaseline.alphabetic => 0.0,
|
||||||
|
TextBaseline.ideographic => (input.getDryBaseline(layout.inputConstraints, TextBaseline.ideographic) ?? input.getDryLayout(layout.inputConstraints).height) - (input.getDryBaseline(layout.inputConstraints, TextBaseline.alphabetic) ?? input.getDryLayout(layout.inputConstraints).height),
|
||||||
|
} + layout.baseline;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Size computeDryLayout(BoxConstraints constraints) {
|
Size computeDryLayout(BoxConstraints constraints) {
|
||||||
assert(debugCannotComputeDryLayout(
|
final _RenderDecorationLayout layout = _layout(
|
||||||
reason: 'Layout requires baseline metrics, which are only available after a full layout.',
|
constraints,
|
||||||
));
|
layoutChild: ChildLayoutHelper.dryLayoutChild,
|
||||||
return Size.zero;
|
getBaseline: _getDryBaseline,
|
||||||
|
);
|
||||||
|
return constraints.constrain(layout.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void performLayout() {
|
void performLayout() {
|
||||||
final BoxConstraints constraints = this.constraints;
|
final BoxConstraints constraints = this.constraints;
|
||||||
_labelTransform = null;
|
_labelTransform = null;
|
||||||
final _RenderDecorationLayout layout = _layout(constraints);
|
final _RenderDecorationLayout layout = _layout(
|
||||||
|
constraints,
|
||||||
|
layoutChild: ChildLayoutHelper.layoutChild,
|
||||||
|
getBaseline: _getBaseline,
|
||||||
|
);
|
||||||
size = constraints.constrain(layout.size);
|
size = constraints.constrain(layout.size);
|
||||||
assert(size.width == constraints.constrainWidth(layout.size.width));
|
assert(size.width == constraints.constrainWidth(layout.size.width));
|
||||||
assert(size.height == constraints.constrainHeight(layout.size.height));
|
assert(size.height == constraints.constrainHeight(layout.size.height));
|
||||||
|
Loading…
Reference in New Issue
Block a user