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 isDrawingCheckmark => theme.showCheckmark && !checkmarkAnimation.isDismissed;
|
||||||
bool get deleteIconShowing => !deleteDrawerAnimation.isDismissed;
|
bool get deleteIconShowing => !deleteDrawerAnimation.isDismissed;
|
||||||
|
|
||||||
@override
|
|
||||||
bool get sizedByParent => false;
|
|
||||||
|
|
||||||
static Rect _boxRect(RenderBox box) => _boxParentData(box).offset & box.size;
|
static Rect _boxRect(RenderBox box) => _boxParentData(box).offset & box.size;
|
||||||
|
|
||||||
static BoxParentData _boxParentData(RenderBox box) => box.parentData! as BoxParentData;
|
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;
|
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
|
// 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.
|
// determine how much to shrink the width constraints for the "real" layout.
|
||||||
final double maxLabelWidth = contentConstraints.maxWidth.isFinite
|
final double freeSpace = contentConstraints.maxWidth - iconWidth - theme.labelPadding.horizontal - theme.padding.horizontal;
|
||||||
? math.max(
|
final double maxLabelWidth = math.max(0.0, freeSpace);
|
||||||
0.0,
|
return BoxConstraints(
|
||||||
contentConstraints.maxWidth - iconSizes - theme.labelPadding.horizontal - theme.padding.horizontal,
|
minHeight: rawLabelSize.height,
|
||||||
)
|
maxHeight: contentSize,
|
||||||
: size.width;
|
maxWidth: maxLabelWidth.isFinite ? maxLabelWidth : rawLabelSize.width,
|
||||||
final BoxConstraints labelConstraints = BoxConstraints(
|
|
||||||
minHeight: rawSize.height,
|
|
||||||
maxHeight: size.height,
|
|
||||||
maxWidth: maxLabelWidth,
|
|
||||||
);
|
);
|
||||||
final Size updatedSize = layoutChild(label, labelConstraints);
|
|
||||||
return theme.labelPadding.inflateSize(updatedSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Size _layoutAvatar(double contentSize, [ChildLayouter layoutChild = ChildLayoutHelper.layoutChild]) {
|
Size _layoutAvatar(double contentSize, [ChildLayouter layoutChild = ChildLayoutHelper.layoutChild]) {
|
||||||
final double requestedSize = math.max(0.0, contentSize);
|
|
||||||
final BoxConstraints avatarConstraints = avatarBoxConstraints ?? BoxConstraints.tightFor(
|
final BoxConstraints avatarConstraints = avatarBoxConstraints ?? BoxConstraints.tightFor(
|
||||||
width: requestedSize,
|
width: contentSize,
|
||||||
height: requestedSize,
|
height: contentSize,
|
||||||
);
|
);
|
||||||
final Size avatarBoxSize = layoutChild(avatar, avatarConstraints);
|
final Size avatarBoxSize = layoutChild(avatar, avatarConstraints);
|
||||||
if (!theme.showCheckmark && !theme.showAvatar) {
|
if (!theme.showCheckmark && !theme.showAvatar) {
|
||||||
@ -1808,10 +1798,9 @@ class _RenderChip extends RenderBox with SlottedContainerRenderObjectMixin<_Chip
|
|||||||
}
|
}
|
||||||
|
|
||||||
Size _layoutDeleteIcon(double contentSize, [ChildLayouter layoutChild = ChildLayoutHelper.layoutChild]) {
|
Size _layoutDeleteIcon(double contentSize, [ChildLayouter layoutChild = ChildLayoutHelper.layoutChild]) {
|
||||||
final double requestedSize = math.max(0.0, contentSize);
|
|
||||||
final BoxConstraints deleteIconConstraints = deleteIconBoxConstraints ?? BoxConstraints.tightFor(
|
final BoxConstraints deleteIconConstraints = deleteIconBoxConstraints ?? BoxConstraints.tightFor(
|
||||||
width: requestedSize,
|
width: contentSize,
|
||||||
height: requestedSize,
|
height: contentSize,
|
||||||
);
|
);
|
||||||
final Size boxSize = layoutChild(deleteIcon, deleteIconConstraints);
|
final Size boxSize = layoutChild(deleteIcon, deleteIconConstraints);
|
||||||
if (!deleteIconShowing) {
|
if (!deleteIconShowing) {
|
||||||
@ -1851,25 +1840,36 @@ class _RenderChip extends RenderBox with SlottedContainerRenderObjectMixin<_Chip
|
|||||||
return _computeSizes(constraints, ChildLayoutHelper.dryLayoutChild).size;
|
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) {
|
_ChipSizes _computeSizes(BoxConstraints constraints, ChildLayouter layoutChild) {
|
||||||
final BoxConstraints contentConstraints = constraints.loosen();
|
final BoxConstraints contentConstraints = constraints.loosen();
|
||||||
// Find out the height of the label within the constraints.
|
// 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 = label.getDryLayout(contentConstraints);
|
||||||
final Size rawLabelSize = layoutChild(label, contentConstraints);
|
|
||||||
final double contentSize = math.max(
|
final double contentSize = math.max(
|
||||||
_kChipHeight - theme.padding.vertical + theme.labelPadding.vertical,
|
_kChipHeight - theme.padding.vertical + theme.labelPadding.vertical,
|
||||||
rawLabelSize.height + theme.labelPadding.vertical,
|
rawLabelSize.height + theme.labelPadding.vertical,
|
||||||
);
|
);
|
||||||
|
assert(contentSize >= rawLabelSize.height);
|
||||||
final Size avatarSize = _layoutAvatar(contentSize, layoutChild);
|
final Size avatarSize = _layoutAvatar(contentSize, layoutChild);
|
||||||
final Size deleteIconSize = _layoutDeleteIcon(contentSize, layoutChild);
|
final Size deleteIconSize = _layoutDeleteIcon(contentSize, layoutChild);
|
||||||
final Size labelSize = _layoutLabel(
|
|
||||||
|
final BoxConstraints labelConstraints = _labelConstraintsFrom(
|
||||||
contentConstraints,
|
contentConstraints,
|
||||||
avatarSize.width + deleteIconSize.width,
|
avatarSize.width + deleteIconSize.width,
|
||||||
Size(rawLabelSize.width, contentSize),
|
contentSize,
|
||||||
rawLabelSize,
|
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
|
// This is the overall size of the content: it doesn't include
|
||||||
// theme.padding, that is added in at the end.
|
// theme.padding, that is added in at the end.
|
||||||
final Size overallSize = Size(
|
final Size overallSize = Size(
|
||||||
@ -1887,6 +1887,7 @@ class _RenderChip extends RenderBox with SlottedContainerRenderObjectMixin<_Chip
|
|||||||
content: contentSize,
|
content: contentSize,
|
||||||
densityAdjustment: densityAdjustment,
|
densityAdjustment: densityAdjustment,
|
||||||
avatar: avatarSize,
|
avatar: avatarSize,
|
||||||
|
labelConstraints: labelConstraints,
|
||||||
label: labelSize,
|
label: labelSize,
|
||||||
deleteIcon: deleteIconSize,
|
deleteIcon: deleteIconSize,
|
||||||
);
|
);
|
||||||
@ -2232,6 +2233,7 @@ class _ChipSizes {
|
|||||||
required this.overall,
|
required this.overall,
|
||||||
required this.content,
|
required this.content,
|
||||||
required this.avatar,
|
required this.avatar,
|
||||||
|
required this.labelConstraints,
|
||||||
required this.label,
|
required this.label,
|
||||||
required this.deleteIcon,
|
required this.deleteIcon,
|
||||||
required this.densityAdjustment,
|
required this.densityAdjustment,
|
||||||
@ -2240,6 +2242,7 @@ class _ChipSizes {
|
|||||||
final Size overall;
|
final Size overall;
|
||||||
final double content;
|
final double content;
|
||||||
final Size avatar;
|
final Size avatar;
|
||||||
|
final BoxConstraints labelConstraints;
|
||||||
final Size label;
|
final Size label;
|
||||||
final Size deleteIcon;
|
final Size deleteIcon;
|
||||||
final Offset densityAdjustment;
|
final Offset densityAdjustment;
|
||||||
|
@ -5781,6 +5781,18 @@ void main() {
|
|||||||
// Test rendered icon color.
|
// Test rendered icon color.
|
||||||
expect(getIconStyle(tester, deleteIcon)?.color, deleteIconColor);
|
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 {
|
class _MaterialStateOutlinedBorder extends StadiumBorder implements MaterialStateOutlinedBorder {
|
||||||
@ -5800,3 +5812,16 @@ class _MaterialStateBorderSide extends MaterialStateBorderSide {
|
|||||||
@override
|
@override
|
||||||
BorderSide? resolve(Set<MaterialState> states) => resolver(states);
|
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