Skip to content

Commit f76eda1

Browse files
_RenderDecorator.computeDryBaseline (#146365)
Depends on flutter/flutter#146363 No test because the consistency of the `computeDryBaseline` implementations is checked at paint time.
1 parent 21da3a8 commit f76eda1

File tree

1 file changed

+72
-31
lines changed

1 file changed

+72
-31
lines changed

packages/flutter/lib/src/material/input_decorator.dart

Lines changed: 72 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -697,12 +697,14 @@ class _Decoration {
697697
// all of the renderer children of a _RenderDecoration.
698698
class _RenderDecorationLayout {
699699
const _RenderDecorationLayout({
700+
required this.inputConstraints,
700701
required this.baseline,
701702
required this.containerHeight,
702703
required this.subtextSize,
703704
required this.size,
704705
});
705706

707+
final BoxConstraints inputConstraints;
706708
final double baseline;
707709
final double containerHeight;
708710
final _SubtextSize? subtextSize;
@@ -903,6 +905,10 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin
903905
static double _getBaseline(RenderBox box, BoxConstraints boxConstraints) {
904906
return ChildLayoutHelper.getBaseline(box, boxConstraints, TextBaseline.alphabetic) ?? box.size.height;
905907
}
908+
static double _getDryBaseline(RenderBox box, BoxConstraints boxConstraints) {
909+
return ChildLayoutHelper.getDryBaseline(box, boxConstraints, TextBaseline.alphabetic)
910+
?? ChildLayoutHelper.dryLayoutChild(box, boxConstraints).height;
911+
}
906912

907913
static BoxParentData _boxParentData(RenderBox box) => box.parentData! as BoxParentData;
908914

@@ -943,7 +949,11 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin
943949
// Returns a value used by performLayout to position all of the renderers.
944950
// This method applies layout to all of the renderers except the container.
945951
// For convenience, the container is laid out in performLayout().
946-
_RenderDecorationLayout _layout(BoxConstraints constraints) {
952+
_RenderDecorationLayout _layout(
953+
BoxConstraints constraints, {
954+
required ChildLayouter layoutChild,
955+
required _ChildBaselineGetter getBaseline,
956+
}) {
947957
assert(
948958
constraints.maxWidth < double.infinity,
949959
'An InputDecorator, which is typically created by a TextField, cannot '
@@ -958,34 +968,36 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin
958968
final BoxConstraints boxConstraints = constraints.loosen();
959969

960970
// Layout all the widgets used by InputDecorator
961-
final double iconWidth = (icon?..layout(boxConstraints, parentUsesSize: true))?.size.width ?? 0.0;
971+
final RenderBox? icon = this.icon;
972+
final double iconWidth = icon == null ? 0.0 : layoutChild(icon, boxConstraints).width;
962973
final BoxConstraints containerConstraints = boxConstraints.deflate(EdgeInsets.only(left: iconWidth));
963974
final BoxConstraints contentConstraints = containerConstraints.deflate(EdgeInsets.only(left: contentPadding.horizontal));
964975

965976
// The helper or error text can occupy the full width less the space
966977
// occupied by the icon and counter.
967978
final _SubtextSize? subtextSize = _computeSubtextSizes(
968979
constraints: contentConstraints,
969-
layoutChild: ChildLayoutHelper.layoutChild,
970-
getBaseline: _getBaseline,
980+
layoutChild: layoutChild,
981+
getBaseline: getBaseline,
971982
);
972983

973984
final RenderBox? prefixIcon = this.prefixIcon;
974985
final RenderBox? suffixIcon = this.suffixIcon;
975-
final Size prefixIconSize = (prefixIcon?..layout(containerConstraints, parentUsesSize: true))?.size ?? Size.zero;
976-
final Size suffixIconSize = (suffixIcon?..layout(containerConstraints, parentUsesSize: true))?.size ?? Size.zero;
986+
final Size prefixIconSize = prefixIcon == null ? Size.zero : layoutChild(prefixIcon, containerConstraints);
987+
final Size suffixIconSize = suffixIcon == null ? Size.zero : layoutChild(suffixIcon, containerConstraints);
977988
final RenderBox? prefix = this.prefix;
978989
final RenderBox? suffix = this.suffix;
979-
final Size prefixSize = (prefix?..layout(contentConstraints, parentUsesSize: true))?.size ?? Size.zero;
980-
final Size suffixSize = (suffix?..layout(contentConstraints, parentUsesSize: true))?.size ?? Size.zero;
990+
final Size prefixSize = prefix == null ? Size.zero : layoutChild(prefix, contentConstraints);
991+
final Size suffixSize = suffix == null ? Size.zero : layoutChild(suffix, contentConstraints);
981992

982993
final EdgeInsetsDirectional accessoryHorizontalInsets = EdgeInsetsDirectional.only(
983-
start: iconWidth + prefixSize.width + (prefixIcon == null ? contentPadding.start : prefixIcon.size.width),
984-
end: suffixSize.width + (suffixIcon == null ? contentPadding.end : suffixIcon.size.width),
994+
start: iconWidth + prefixSize.width + (prefixIcon == null ? contentPadding.start : prefixIconSize.width),
995+
end: suffixSize.width + (suffixIcon == null ? contentPadding.end : suffixIconSize.width),
985996
);
986997

987998
final double inputWidth = math.max(0.0, constraints.maxWidth - accessoryHorizontalInsets.horizontal);
988999
final RenderBox? label = this.label;
1000+
final double topHeight;
9891001
if (label != null) {
9901002
final double suffixIconSpace = decoration.border.isOutline
9911003
? lerpDouble(suffixIconSize.width, 0.0, decoration.floatingLabelProgress)!
@@ -995,18 +1007,21 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin
9951007
constraints.maxWidth - (iconWidth + contentPadding.horizontal + prefixIconSize.width + suffixIconSpace),
9961008
);
9971009

998-
// Increase the available width for the label when it is scaled down.
999-
final double invertedLabelScale = lerpDouble(1.00, 1 / _kFinalLabelScale, decoration.floatingLabelProgress)!;
1010+
// Increase the available width for the label when it is scaled down.
1011+
final double invertedLabelScale = lerpDouble(1.00, 1 / _kFinalLabelScale, decoration.floatingLabelProgress)!;
10001012
final BoxConstraints labelConstraints = boxConstraints.copyWith(maxWidth: labelWidth * invertedLabelScale);
1001-
label.layout(labelConstraints, parentUsesSize: true);
1013+
layoutChild(label, labelConstraints);
1014+
1015+
final double labelHeight = decoration.floatingLabelHeight;
1016+
topHeight = decoration.border.isOutline
1017+
? math.max(labelHeight - getBaseline(label, labelConstraints), 0.0)
1018+
: labelHeight;
1019+
} else {
1020+
topHeight = 0.0;
10021021
}
10031022

10041023
// The height of the input needs to accommodate label above and counter and
10051024
// helperError below, when they exist.
1006-
final double labelHeight = label == null ? 0 : decoration.floatingLabelHeight;
1007-
final double topHeight = decoration.border.isOutline
1008-
? math.max(labelHeight - (label?.getDistanceToBaseline(TextBaseline.alphabetic) ?? 0.0), 0.0)
1009-
: labelHeight;
10101025
final double bottomHeight = subtextSize?.bottomHeight ?? 0.0;
10111026
final Offset densityOffset = decoration.visualDensity.baseSizeAdjustment;
10121027
final BoxConstraints inputConstraints = boxConstraints
@@ -1015,17 +1030,18 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin
10151030

10161031
final RenderBox? input = this.input;
10171032
final RenderBox? hint = this.hint;
1018-
final Size inputSize = (input?..layout(inputConstraints, parentUsesSize: true))?.size ?? Size.zero;
1019-
final Size hintSize = (hint?..layout(boxConstraints.tighten(width: inputWidth), parentUsesSize: true))?.size ?? Size.zero;
1020-
final double inputBaseline = input == null ? 0.0 : _getBaseline(input, inputConstraints);
1021-
final double hintBaseline = hint == null ? 0.0 : _getBaseline(hint, boxConstraints.tighten(width: inputWidth));
1033+
final Size inputSize = input == null ? Size.zero : layoutChild(input, inputConstraints);
1034+
final Size hintSize = hint == null ? Size.zero : layoutChild(hint, boxConstraints.tighten(width: inputWidth));
1035+
final double inputBaseline = input == null ? 0.0 : getBaseline(input, inputConstraints);
1036+
final double hintBaseline = hint == null ? 0.0 : getBaseline(hint, boxConstraints.tighten(width: inputWidth));
10221037

10231038
// The field can be occupied by a hint or by the input itself
10241039
final double inputHeight = math.max(hintSize.height, inputSize.height);
10251040
final double inputInternalBaseline = math.max(inputBaseline, hintBaseline);
10261041

1027-
final double prefixBaseline = prefix == null ? 0.0 : _getBaseline(prefix, contentConstraints);
1028-
final double suffixBaseline = suffix == null ? 0.0 : _getBaseline(suffix, contentConstraints);
1042+
final double prefixBaseline = prefix == null ? 0.0 : getBaseline(prefix, contentConstraints);
1043+
final double suffixBaseline = suffix == null ? 0.0 : getBaseline(suffix, contentConstraints);
1044+
10291045
// Calculate the amount that prefix/suffix affects height above and below
10301046
// the input.
10311047
final double fixHeight = math.max(prefixBaseline, suffixBaseline);
@@ -1117,6 +1133,7 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin
11171133
}
11181134

11191135
return _RenderDecorationLayout(
1136+
inputConstraints: inputConstraints,
11201137
containerHeight: containerHeight,
11211138
baseline: baseline,
11221139
subtextSize: subtextSize,
@@ -1237,27 +1254,51 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin
12371254
@override
12381255
double computeDistanceToActualBaseline(TextBaseline baseline) {
12391256
final RenderBox? input = this.input;
1240-
return input == null
1241-
? 0.0
1242-
: _boxParentData(input).offset.dy + (input.getDistanceToActualBaseline(baseline) ?? 0.0);
1257+
if (input == null) {
1258+
return 0.0;
1259+
}
1260+
return _boxParentData(input).offset.dy + (input.getDistanceToActualBaseline(baseline) ?? input.size.height);
12431261
}
12441262

12451263
// Records where the label was painted.
12461264
Matrix4? _labelTransform;
12471265

1266+
@override
1267+
double? computeDryBaseline(covariant BoxConstraints constraints, TextBaseline baseline) {
1268+
final RenderBox? input = this.input;
1269+
if (input == null) {
1270+
return 0.0;
1271+
}
1272+
final _RenderDecorationLayout layout = _layout(
1273+
constraints,
1274+
layoutChild: ChildLayoutHelper.dryLayoutChild,
1275+
getBaseline: _getDryBaseline,
1276+
);
1277+
return switch (baseline) {
1278+
TextBaseline.alphabetic => 0.0,
1279+
TextBaseline.ideographic => (input.getDryBaseline(layout.inputConstraints, TextBaseline.ideographic) ?? input.getDryLayout(layout.inputConstraints).height) - (input.getDryBaseline(layout.inputConstraints, TextBaseline.alphabetic) ?? input.getDryLayout(layout.inputConstraints).height),
1280+
} + layout.baseline;
1281+
}
1282+
12481283
@override
12491284
Size computeDryLayout(BoxConstraints constraints) {
1250-
assert(debugCannotComputeDryLayout(
1251-
reason: 'Layout requires baseline metrics, which are only available after a full layout.',
1252-
));
1253-
return Size.zero;
1285+
final _RenderDecorationLayout layout = _layout(
1286+
constraints,
1287+
layoutChild: ChildLayoutHelper.dryLayoutChild,
1288+
getBaseline: _getDryBaseline,
1289+
);
1290+
return constraints.constrain(layout.size);
12541291
}
12551292

12561293
@override
12571294
void performLayout() {
12581295
final BoxConstraints constraints = this.constraints;
12591296
_labelTransform = null;
1260-
final _RenderDecorationLayout layout = _layout(constraints);
1297+
final _RenderDecorationLayout layout = _layout(
1298+
constraints,
1299+
layoutChild: ChildLayoutHelper.layoutChild,
1300+
getBaseline: _getBaseline,
1301+
);
12611302
size = constraints.constrain(layout.size);
12621303
assert(size.width == constraints.constrainWidth(layout.size.width));
12631304
assert(size.height == constraints.constrainHeight(layout.size.height));

0 commit comments

Comments
 (0)