From 7690bb47dc55b387ea837d2a06164b00fb5036e5 Mon Sep 17 00:00:00 2001 From: Shi-Hao Hong Date: Wed, 1 May 2019 13:46:36 -0700 Subject: [PATCH] Add Horizontal Padding to Constrained Chip Label Calculations (#31861) * Add horizontal padding and properly constrain chip label calculations * Added regression test for avatar, label and delete icon constraint --- packages/flutter/lib/src/material/chip.dart | 37 ++++++---- packages/flutter/test/material/chip_test.dart | 73 +++++++++++++++++++ 2 files changed, 97 insertions(+), 13 deletions(-) diff --git a/packages/flutter/lib/src/material/chip.dart b/packages/flutter/lib/src/material/chip.dart index 11d4ceb117..41d837679b 100644 --- a/packages/flutter/lib/src/material/chip.dart +++ b/packages/flutter/lib/src/material/chip.dart @@ -2188,29 +2188,40 @@ class _RenderChip extends RenderBox { // 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. if (constraints.maxWidth.isFinite) { + final double maxWidth = math.max( + 0.0, + constraints.maxWidth + - iconSizes + - theme.labelPadding.horizontal + - theme.padding.horizontal, + ); label.layout( constraints.copyWith( minWidth: 0.0, - maxWidth: math.max( - 0.0, - constraints.maxWidth - iconSizes - theme.labelPadding.horizontal, - ), + maxWidth: maxWidth, minHeight: rawSize.height, maxHeight: size.height, ), parentUsesSize: true, ); - } else { - label.layout( - BoxConstraints( - minHeight: rawSize.height, - maxHeight: size.height, - minWidth: 0.0, - maxWidth: size.width, - ), - parentUsesSize: true, + + final Size updatedSize = _boxSize(label); + return Size( + updatedSize.width + theme.labelPadding.horizontal, + updatedSize.height + theme.labelPadding.vertical, ); } + + label.layout( + BoxConstraints( + minHeight: rawSize.height, + maxHeight: size.height, + minWidth: 0.0, + maxWidth: size.width, + ), + parentUsesSize: true, + ); + return Size( rawSize.width + theme.labelPadding.horizontal, rawSize.height + theme.labelPadding.vertical, diff --git a/packages/flutter/test/material/chip_test.dart b/packages/flutter/test/material/chip_test.dart index 225d472be0..2185bcaf7a 100644 --- a/packages/flutter/test/material/chip_test.dart +++ b/packages/flutter/test/material/chip_test.dart @@ -248,6 +248,79 @@ void main() { ); }); + testWidgets( + 'Chip constrains the avatar, label, and delete icons to the bounds of ' + 'the chip when it exceeds the available space', (WidgetTester tester) async { + // Regression test for https://github.com/flutter/flutter/issues/11523 + Widget chipBuilder (String text, {Widget avatar, VoidCallback onDeleted}) { + return MaterialApp( + home: Scaffold( + body: Container( + width: 150, + child: Column( + children: [ + Chip( + avatar: avatar, + label: Text(text), + onDeleted: onDeleted, + ), + ] + ), + ), + ), + ); + } + + void chipRectContains(Rect chipRect, Rect rect) { + expect(chipRect.contains(rect.topLeft), true); + expect(chipRect.contains(rect.topRight), true); + expect(chipRect.contains(rect.bottomLeft), true); + expect(chipRect.contains(rect.bottomRight), true); + } + + Rect chipRect; + Rect avatarRect; + Rect labelRect; + Rect deleteIconRect; + const String text = 'Very long text that will be clipped'; + + await tester.pumpWidget(chipBuilder(text)); + + chipRect = tester.getRect(find.byType(Chip)); + labelRect = tester.getRect(find.text(text)); + chipRectContains(chipRect, labelRect); + + await tester.pumpWidget(chipBuilder( + text, + avatar: const CircleAvatar(child: Text('A')), + )); + await tester.pumpAndSettle(); + + chipRect = tester.getRect(find.byType(Chip)); + avatarRect = tester.getRect(find.byType(CircleAvatar)); + chipRectContains(chipRect, avatarRect); + + labelRect = tester.getRect(find.text(text)); + chipRectContains(chipRect, labelRect); + + await tester.pumpWidget(chipBuilder( + text, + avatar: const CircleAvatar(child: Text('A')), + onDeleted: () {}, + )); + await tester.pumpAndSettle(); + + chipRect = tester.getRect(find.byType(Chip)); + avatarRect = tester.getRect(find.byType(CircleAvatar)); + chipRectContains(chipRect, avatarRect); + + labelRect = tester.getRect(find.text(text)); + chipRectContains(chipRect, labelRect); + + deleteIconRect = tester.getRect(find.byIcon(Icons.cancel)); + chipRectContains(chipRect, deleteIconRect); + }); + testWidgets('Chip in row works ok', (WidgetTester tester) async { const TextStyle style = TextStyle(fontFamily: 'Ahem', fontSize: 10.0); await tester.pumpWidget(