Skip to content

Commit cfabdca

Browse files
authored
Fix chips use square delete button InkWell shape instead of circular (#144319)
fixes [Chips delete button hover style is square, not circular](flutter/flutter#141335) ### Code sample <details> <summary>expand to view the code sample</summary> ```dart import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @OverRide Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: Center( child: RawChip( label: const Text('Test'), onPressed: null, deleteIcon: const Icon(Icons.clear, size: 18), onDeleted: () {}, ), ), ), ); } } ``` </details> ### Preview | Before | After | | --------------- | --------------- | | <img src="https://github.com/flutter/flutter/assets/48603081/c5d62c57-97b3-4f94-b83d-df13559ee3a8" /> | <img src="https://github.com/flutter/flutter/assets/48603081/b76edaab-73e0-4aa9-8ca2-127eedd77814" /> |
1 parent e8f8a8d commit cfabdca

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,7 @@ class _RawChipState extends State<RawChip> with MaterialStateMixin, TickerProvid
11911191
radius: (_kChipHeight + (widget.padding?.vertical ?? 0.0)) * .45,
11921192
// Keeps the splash from being constrained to the icon alone.
11931193
splashFactory: _UnconstrainedInkSplashFactory(Theme.of(context).splashFactory),
1194+
customBorder: const CircleBorder(),
11941195
onTap: widget.isEnabled ? widget.onDeleted : null,
11951196
child: IconTheme(
11961197
data: theme.iconTheme.copyWith(

packages/flutter/test/material/chip_test.dart

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ Widget chipWithOptionalDeleteButton({
144144
TextDirection textDirection = TextDirection.ltr,
145145
String? chipTooltip,
146146
String? deleteButtonTooltipMessage,
147+
double? size,
147148
VoidCallback? onPressed = doNothing,
148149
ThemeData? themeData,
149150
}) {
@@ -156,7 +157,11 @@ Widget chipWithOptionalDeleteButton({
156157
tooltip: chipTooltip,
157158
onPressed: onPressed,
158159
onDeleted: deletable ? doNothing : null,
159-
deleteIcon: Icon(Icons.close, key: deleteButtonKey),
160+
deleteIcon: Icon(
161+
key: deleteButtonKey,
162+
size: size,
163+
Icons.close,
164+
),
160165
deleteButtonTooltipMessage: deleteButtonTooltipMessage,
161166
label: Text(
162167
deletable
@@ -1852,6 +1857,7 @@ void main() {
18521857
labelKey: labelKey,
18531858
deleteButtonKey: deleteButtonKey,
18541859
deletable: true,
1860+
size: 18.0,
18551861
),
18561862
);
18571863

@@ -1957,6 +1963,7 @@ void main() {
19571963
onPressed: null,
19581964
deleteButtonKey: deleteButtonKey,
19591965
deletable: true,
1966+
size: 18.0,
19601967
),
19611968
);
19621969

@@ -5385,6 +5392,62 @@ void main() {
53855392
expect(labelTopRight.dx, deleteIconCenter.dx - (iconSize / 2) - labelPadding);
53865393
});
53875394

5395+
testWidgets('Default delete button InkWell shape', (WidgetTester tester) async {
5396+
await tester.pumpWidget(wrapForChip(
5397+
child: Center(
5398+
child: RawChip(
5399+
onDeleted: () { },
5400+
label: const Text('RawChip'),
5401+
),
5402+
),
5403+
));
5404+
5405+
final InkWell deleteButtonInkWell = tester.widget<InkWell>(find.ancestor(
5406+
of: find.byIcon(Icons.cancel),
5407+
matching: find.byType(InkWell).last,
5408+
));
5409+
expect(deleteButtonInkWell.customBorder, const CircleBorder());
5410+
});
5411+
5412+
testWidgets('Default delete button overlay', (WidgetTester tester) async {
5413+
final ThemeData theme = ThemeData();
5414+
await tester.pumpWidget(wrapForChip(
5415+
child: Center(
5416+
child: RawChip(
5417+
onDeleted: () { },
5418+
label: const Text('RawChip'),
5419+
),
5420+
),
5421+
theme: theme,
5422+
));
5423+
5424+
RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
5425+
expect(inkFeatures, isNot(paints..rect(color: theme.hoverColor)));
5426+
expect(inkFeatures, paintsExactlyCountTimes(#clipPath, 0));
5427+
5428+
// Hover over the delete icon.
5429+
final Offset centerOfDeleteButton = tester.getCenter(find.byType(Icon));
5430+
final TestGesture hoverGesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
5431+
await hoverGesture.moveTo(centerOfDeleteButton);
5432+
addTearDown(hoverGesture.removePointer);
5433+
await tester.pumpAndSettle();
5434+
5435+
inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
5436+
expect(inkFeatures, paints..rect(color: theme.hoverColor));
5437+
expect(inkFeatures, paintsExactlyCountTimes(#clipPath, 1));
5438+
5439+
const Rect expectedClipRect = Rect.fromLTRB(124.7, 10.0, 142.7, 28.0);
5440+
final Path expectedClipPath = Path()..addRect(expectedClipRect);
5441+
expect(
5442+
inkFeatures,
5443+
paints..clipPath(pathMatcher: coversSameAreaAs(
5444+
expectedClipPath,
5445+
areaToCompare: expectedClipRect.inflate(48.0),
5446+
sampleSize: 100,
5447+
)),
5448+
);
5449+
});
5450+
53885451
group('Material 2', () {
53895452
// These tests are only relevant for Material 2. Once Material 2
53905453
// support is deprecated and the APIs are removed, these tests

0 commit comments

Comments
 (0)