From e9a4759947307e8208cfe8fda98b2f25ba4e8de1 Mon Sep 17 00:00:00 2001 From: jBrennen Date: Fri, 5 Jun 2020 00:33:02 +0100 Subject: [PATCH] #57730 - Support custom shapes for ListTiles (#57733) --- .../flutter/lib/src/material/list_tile.dart | 19 +++++++++++++++++++ .../flutter/test/material/list_tile_test.dart | 10 ++++++++++ 2 files changed, 29 insertions(+) diff --git a/packages/flutter/lib/src/material/list_tile.dart b/packages/flutter/lib/src/material/list_tile.dart index 4f4f1b91f10..7a0fdd61200 100644 --- a/packages/flutter/lib/src/material/list_tile.dart +++ b/packages/flutter/lib/src/material/list_tile.dart @@ -44,6 +44,7 @@ class ListTileTheme extends InheritedTheme { const ListTileTheme({ Key key, this.dense = false, + this.shape, this.style = ListTileStyle.list, this.selectedColor, this.iconColor, @@ -59,6 +60,7 @@ class ListTileTheme extends InheritedTheme { static Widget merge({ Key key, bool dense, + ShapeBorder shape, ListTileStyle style, Color selectedColor, Color iconColor, @@ -73,6 +75,7 @@ class ListTileTheme extends InheritedTheme { return ListTileTheme( key: key, dense: dense ?? parent.dense, + shape: shape ?? parent.shape, style: style ?? parent.style, selectedColor: selectedColor ?? parent.selectedColor, iconColor: iconColor ?? parent.iconColor, @@ -87,6 +90,9 @@ class ListTileTheme extends InheritedTheme { /// If true then [ListTile]s will have the vertically dense layout. final bool dense; + /// If specified, [shape] defines the shape of the [ListTile]'s [InkWell] border. + final ShapeBorder shape; + /// If specified, [style] defines the font used for [ListTile] titles. final ListTileStyle style; @@ -122,6 +128,7 @@ class ListTileTheme extends InheritedTheme { final ListTileTheme ancestorTheme = context.findAncestorWidgetOfExactType(); return identical(this, ancestorTheme) ? child : ListTileTheme( dense: dense, + shape: shape, style: style, selectedColor: selectedColor, iconColor: iconColor, @@ -134,6 +141,7 @@ class ListTileTheme extends InheritedTheme { @override bool updateShouldNotify(ListTileTheme oldWidget) { return dense != oldWidget.dense + || shape != oldWidget.shape || style != oldWidget.style || selectedColor != oldWidget.selectedColor || iconColor != oldWidget.iconColor @@ -637,6 +645,7 @@ class ListTile extends StatelessWidget { this.isThreeLine = false, this.dense, this.visualDensity, + this.shape, this.contentPadding, this.enabled = true, this.onTap, @@ -713,6 +722,15 @@ class ListTile extends StatelessWidget { /// within a [Theme]. final VisualDensity visualDensity; + /// The shape of the tile's [InkWell]. + /// + /// Defines the tile's [InkWell.customBorder]. + /// + /// If this property is null then [ThemeData.cardTheme.shape] is used. + /// If that's null then the shape will be a [RoundedRectangleBorder] with a + /// circular corner radius of 4.0. + final ShapeBorder shape; + /// The tile's internal padding. /// /// Insets a [ListTile]'s contents: its [leading], [title], [subtitle], @@ -932,6 +950,7 @@ class ListTile extends StatelessWidget { ); return InkWell( + customBorder: shape ?? tileTheme.shape, onTap: enabled ? onTap : null, onLongPress: enabled ? onLongPress : null, mouseCursor: effectiveMouseCursor, diff --git a/packages/flutter/test/material/list_tile_test.dart b/packages/flutter/test/material/list_tile_test.dart index 37ab63f7705..b1b5b6313df 100644 --- a/packages/flutter/test/material/list_tile_test.dart +++ b/packages/flutter/test/material/list_tile_test.dart @@ -263,6 +263,7 @@ void main() { bool enabled = true, bool dense = false, bool selected = false, + ShapeBorder shape, Color selectedColor, Color iconColor, Color textColor, @@ -272,6 +273,7 @@ void main() { child: Center( child: ListTileTheme( dense: dense, + shape: shape, selectedColor: selectedColor, iconColor: iconColor, textColor: textColor, @@ -296,9 +298,13 @@ void main() { const Color green = Color(0xFF00FF00); const Color red = Color(0xFFFF0000); + const ShapeBorder roundedShape = RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(4.0)), + ); Color iconColor(Key key) => tester.state(find.byKey(key)).iconTheme.color; Color textColor(Key key) => tester.state(find.byKey(key)).textStyle.color; + ShapeBorder inkWellBorder() => tester.widget(find.descendant(of: find.byType(ListTile), matching: find.byType(InkWell))).customBorder; // A selected ListTile's leading, trailing, and text get the primary color by default await tester.pumpWidget(buildFrame(selected: true)); @@ -341,6 +347,10 @@ void main() { expect(iconColor(trailingKey), theme.disabledColor); expect(textColor(titleKey), theme.disabledColor); expect(textColor(subtitleKey), theme.disabledColor); + + // A selected ListTile's InkWell gets the ListTileTheme's shape + await tester.pumpWidget(buildFrame(selected: true, shape: roundedShape)); + expect(inkWellBorder(), roundedShape); }); testWidgets('ListTile semantics', (WidgetTester tester) async {