Implement computeDryBaseline for RenderChip (#146224)
Also, use `getDryLayout` for the first pass of the `label` layout. The computeDryBaseline stuff doesn't have a test because there're asserts making sure it returns the same result as `computeDistanceToActualBaseline`. I have tried adding `+1` to the return expression and `flutter test` fails.
This commit is contained in:
parent
4abd7352f8
commit
e37b29daa9
@ -1728,9 +1728,6 @@ class _RenderChip extends RenderBox with SlottedContainerRenderObjectMixin<_Chip
|
||||
bool get isDrawingCheckmark => theme.showCheckmark && !checkmarkAnimation.isDismissed;
|
||||
bool get deleteIconShowing => !deleteDrawerAnimation.isDismissed;
|
||||
|
||||
@override
|
||||
bool get sizedByParent => false;
|
||||
|
||||
static Rect _boxRect(RenderBox box) => _boxParentData(box).offset & box.size;
|
||||
|
||||
static BoxParentData _boxParentData(RenderBox box) => box.parentData! as BoxParentData;
|
||||
@ -1775,29 +1772,22 @@ class _RenderChip extends RenderBox with SlottedContainerRenderObjectMixin<_Chip
|
||||
return (BaselineOffset(label.getDistanceToActualBaseline(baseline)) + _boxParentData(label).offset.dy).offset;
|
||||
}
|
||||
|
||||
Size _layoutLabel(BoxConstraints contentConstraints, double iconSizes, Size size, Size rawSize, [ChildLayouter layoutChild = ChildLayoutHelper.layoutChild]) {
|
||||
BoxConstraints _labelConstraintsFrom(BoxConstraints contentConstraints, double iconWidth, double contentSize, Size rawLabelSize) {
|
||||
// Now that we know the label height and the width of the icons, we can
|
||||
// determine how much to shrink the width constraints for the "real" layout.
|
||||
final double maxLabelWidth = contentConstraints.maxWidth.isFinite
|
||||
? math.max(
|
||||
0.0,
|
||||
contentConstraints.maxWidth - iconSizes - theme.labelPadding.horizontal - theme.padding.horizontal,
|
||||
)
|
||||
: size.width;
|
||||
final BoxConstraints labelConstraints = BoxConstraints(
|
||||
minHeight: rawSize.height,
|
||||
maxHeight: size.height,
|
||||
maxWidth: maxLabelWidth,
|
||||
final double freeSpace = contentConstraints.maxWidth - iconWidth - theme.labelPadding.horizontal - theme.padding.horizontal;
|
||||
final double maxLabelWidth = math.max(0.0, freeSpace);
|
||||
return BoxConstraints(
|
||||
minHeight: rawLabelSize.height,
|
||||
maxHeight: contentSize,
|
||||
maxWidth: maxLabelWidth.isFinite ? maxLabelWidth : rawLabelSize.width,
|
||||
);
|
||||
final Size updatedSize = layoutChild(label, labelConstraints);
|
||||
return theme.labelPadding.inflateSize(updatedSize);
|
||||
}
|
||||
|
||||
Size _layoutAvatar(double contentSize, [ChildLayouter layoutChild = ChildLayoutHelper.layoutChild]) {
|
||||
final double requestedSize = math.max(0.0, contentSize);
|
||||
final BoxConstraints avatarConstraints = avatarBoxConstraints ?? BoxConstraints.tightFor(
|
||||
width: requestedSize,
|
||||
height: requestedSize,
|
||||
width: contentSize,
|
||||
height: contentSize,
|
||||
);
|
||||
final Size avatarBoxSize = layoutChild(avatar, avatarConstraints);
|
||||
if (!theme.showCheckmark && !theme.showAvatar) {
|
||||
@ -1808,10 +1798,9 @@ class _RenderChip extends RenderBox with SlottedContainerRenderObjectMixin<_Chip
|
||||
}
|
||||
|
||||
Size _layoutDeleteIcon(double contentSize, [ChildLayouter layoutChild = ChildLayoutHelper.layoutChild]) {
|
||||
final double requestedSize = math.max(0.0, contentSize);
|
||||
final BoxConstraints deleteIconConstraints = deleteIconBoxConstraints ?? BoxConstraints.tightFor(
|
||||
width: requestedSize,
|
||||
height: requestedSize,
|
||||
width: contentSize,
|
||||
height: contentSize,
|
||||
);
|
||||
final Size boxSize = layoutChild(deleteIcon, deleteIconConstraints);
|
||||
if (!deleteIconShowing) {
|
||||
@ -1851,25 +1840,36 @@ class _RenderChip extends RenderBox with SlottedContainerRenderObjectMixin<_Chip
|
||||
return _computeSizes(constraints, ChildLayoutHelper.dryLayoutChild).size;
|
||||
}
|
||||
|
||||
@override
|
||||
double? computeDryBaseline(BoxConstraints constraints, TextBaseline baseline) {
|
||||
final _ChipSizes sizes = _computeSizes(constraints, ChildLayoutHelper.dryLayoutChild);
|
||||
final BaselineOffset labelBaseline = BaselineOffset(label.getDryBaseline(sizes.labelConstraints, baseline))
|
||||
+ (sizes.content - sizes.label.height + sizes.densityAdjustment.dy) / 2
|
||||
+ theme.padding.top + theme.labelPadding.top;
|
||||
return labelBaseline.offset;
|
||||
}
|
||||
|
||||
_ChipSizes _computeSizes(BoxConstraints constraints, ChildLayouter layoutChild) {
|
||||
final BoxConstraints contentConstraints = constraints.loosen();
|
||||
// Find out the height of the label within the constraints.
|
||||
final Offset densityAdjustment = Offset(0.0, theme.visualDensity.baseSizeAdjustment.dy / 2.0);
|
||||
final Size rawLabelSize = layoutChild(label, contentConstraints);
|
||||
final Size rawLabelSize = label.getDryLayout(contentConstraints);
|
||||
final double contentSize = math.max(
|
||||
_kChipHeight - theme.padding.vertical + theme.labelPadding.vertical,
|
||||
rawLabelSize.height + theme.labelPadding.vertical,
|
||||
);
|
||||
assert(contentSize >= rawLabelSize.height);
|
||||
final Size avatarSize = _layoutAvatar(contentSize, layoutChild);
|
||||
final Size deleteIconSize = _layoutDeleteIcon(contentSize, layoutChild);
|
||||
final Size labelSize = _layoutLabel(
|
||||
|
||||
final BoxConstraints labelConstraints = _labelConstraintsFrom(
|
||||
contentConstraints,
|
||||
avatarSize.width + deleteIconSize.width,
|
||||
Size(rawLabelSize.width, contentSize),
|
||||
contentSize,
|
||||
rawLabelSize,
|
||||
layoutChild,
|
||||
);
|
||||
|
||||
final Size labelSize = theme.labelPadding.inflateSize(layoutChild(label, labelConstraints));
|
||||
final Offset densityAdjustment = Offset(0.0, theme.visualDensity.baseSizeAdjustment.dy / 2.0);
|
||||
// This is the overall size of the content: it doesn't include
|
||||
// theme.padding, that is added in at the end.
|
||||
final Size overallSize = Size(
|
||||
@ -1887,6 +1887,7 @@ class _RenderChip extends RenderBox with SlottedContainerRenderObjectMixin<_Chip
|
||||
content: contentSize,
|
||||
densityAdjustment: densityAdjustment,
|
||||
avatar: avatarSize,
|
||||
labelConstraints: labelConstraints,
|
||||
label: labelSize,
|
||||
deleteIcon: deleteIconSize,
|
||||
);
|
||||
@ -2232,6 +2233,7 @@ class _ChipSizes {
|
||||
required this.overall,
|
||||
required this.content,
|
||||
required this.avatar,
|
||||
required this.labelConstraints,
|
||||
required this.label,
|
||||
required this.deleteIcon,
|
||||
required this.densityAdjustment,
|
||||
@ -2240,6 +2242,7 @@ class _ChipSizes {
|
||||
final Size overall;
|
||||
final double content;
|
||||
final Size avatar;
|
||||
final BoxConstraints labelConstraints;
|
||||
final Size label;
|
||||
final Size deleteIcon;
|
||||
final Offset densityAdjustment;
|
||||
|
@ -5781,6 +5781,18 @@ void main() {
|
||||
// Test rendered icon color.
|
||||
expect(getIconStyle(tester, deleteIcon)?.color, deleteIconColor);
|
||||
});
|
||||
|
||||
testWidgets('Chip label only does layout once', (WidgetTester tester) async {
|
||||
final RenderLayoutCount renderLayoutCount = RenderLayoutCount();
|
||||
final Widget layoutCounter = Center(
|
||||
key: GlobalKey(),
|
||||
child: WidgetToRenderBoxAdapter(renderBox: renderLayoutCount),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(wrapForChip(child: RawChip(label: layoutCounter)));
|
||||
|
||||
expect(renderLayoutCount.layoutCount, 1);
|
||||
});
|
||||
}
|
||||
|
||||
class _MaterialStateOutlinedBorder extends StadiumBorder implements MaterialStateOutlinedBorder {
|
||||
@ -5800,3 +5812,16 @@ class _MaterialStateBorderSide extends MaterialStateBorderSide {
|
||||
@override
|
||||
BorderSide? resolve(Set<MaterialState> states) => resolver(states);
|
||||
}
|
||||
|
||||
class RenderLayoutCount extends RenderBox {
|
||||
int layoutCount = 0;
|
||||
|
||||
@override
|
||||
Size computeDryLayout(covariant BoxConstraints constraints) => constraints.biggest;
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
layoutCount += 1;
|
||||
size = constraints.biggest;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user