Skip to content

Commit 5116886

Browse files
Add support for ExpansionPanel custom splash color (#147126)
Relates to flutter/flutter#147098 and flutter/flutter#147097 Aside from fixing the expland/collapse icon color in the other PR, I noticed the splash color on both the icon button and the full expansion panel (if ExpansionPanel.canTapOnHeader is set to true) is just `Theme.of(context).splashColor` on the `InkWell` and `Theme.of(context).highlightColor` on the `IconButton` which may not suit the color scheme of the `ExpansionPanel`, so I have added a custom field `splashColor`, which will effect both the `IconButton` and the full panel `Inkwell`.
1 parent cc783cf commit 5116886

File tree

3 files changed

+117
-0
lines changed

3 files changed

+117
-0
lines changed

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ class ExpandIcon extends StatefulWidget {
3939
this.color,
4040
this.disabledColor,
4141
this.expandedColor,
42+
this.splashColor,
43+
this.highlightColor,
4244
});
4345

4446
/// Whether the icon is in an expanded state.
@@ -94,6 +96,20 @@ class ExpandIcon extends StatefulWidget {
9496
/// and for [dark theme](https://material.io/design/color/dark-theme.html#ui-application)
9597
final Color? expandedColor;
9698

99+
/// Defines the splash color of the IconButton.
100+
///
101+
/// If [ThemeData.useMaterial3] is true, this field will be ignored,
102+
/// as [IconButton.splashColor] will be ignored, and you should use
103+
/// [highlightColor] instead.
104+
///
105+
/// Defaults to [ThemeData.splashColor].
106+
final Color? splashColor;
107+
108+
/// Defines the highlight color of the IconButton.
109+
///
110+
/// Defaults to [ThemeData.highlightColor].
111+
final Color? highlightColor;
112+
97113
@override
98114
State<ExpandIcon> createState() => _ExpandIconState();
99115
}
@@ -170,6 +186,8 @@ class _ExpandIconState extends State<ExpandIcon> with SingleTickerProviderStateM
170186
child: IconButton(
171187
padding: widget.padding,
172188
iconSize: widget.size,
189+
highlightColor: widget.highlightColor,
190+
splashColor: widget.splashColor,
173191
color: _iconColor,
174192
disabledColor: widget.disabledColor,
175193
onPressed: widget.onPressed == null ? null : _handlePressed,

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:flutter/widgets.dart';
66

77
import 'constants.dart';
88
import 'expand_icon.dart';
9+
import 'icon_button.dart';
910
import 'ink_well.dart';
1011
import 'material_localizations.dart';
1112
import 'mergeable_material.dart';
@@ -80,6 +81,8 @@ class ExpansionPanel {
8081
this.isExpanded = false,
8182
this.canTapOnHeader = false,
8283
this.backgroundColor,
84+
this.splashColor,
85+
this.highlightColor,
8386
});
8487

8588
/// The widget builder that builds the expansion panels' header.
@@ -95,6 +98,28 @@ class ExpansionPanel {
9598
/// Defaults to false.
9699
final bool isExpanded;
97100

101+
/// Defines the splash color of the panel if [canTapOnHeader] is true,
102+
/// or the splash color of the expand/collapse IconButton if [canTapOnHeader]
103+
/// is false.
104+
///
105+
/// If [canTapOnHeader] is false, and [ThemeData.useMaterial3] is
106+
/// true, this field will be ignored, as [IconButton.splashColor]
107+
/// will be ignored, and you should use [highlightColor] instead.
108+
///
109+
/// If this is null, then the icon button will use its default splash color
110+
/// [ThemeData.splashColor], and the panel will use its default splash color
111+
/// [ThemeData.splashColor] (if [canTapOnHeader] is true).
112+
final Color? splashColor;
113+
114+
/// Defines the highlight color of the panel if [canTapOnHeader] is true, or
115+
/// the highlight color of the expand/collapse IconButton if [canTapOnHeader]
116+
/// is false.
117+
///
118+
/// If this is null, then the icon button will use its default highlight color
119+
/// [ThemeData.highlightColor], and the panel will use its default highlight
120+
/// color [ThemeData.highlightColor] (if [canTapOnHeader] is true).
121+
final Color? highlightColor;
122+
98123
/// Whether tapping on the panel's header will expand/collapse it.
99124
///
100125
/// Defaults to false.
@@ -125,6 +150,8 @@ class ExpansionPanelRadio extends ExpansionPanel {
125150
required super.body,
126151
super.canTapOnHeader,
127152
super.backgroundColor,
153+
super.splashColor,
154+
super.highlightColor,
128155
});
129156

130157
/// The value that uniquely identifies a radio panel so that the currently
@@ -366,6 +393,8 @@ class _ExpansionPanelListState extends State<ExpansionPanelList> {
366393
disabledColor: child.canTapOnHeader ? widget.expandIconColor : null,
367394
isExpanded: _isChildExpanded(index),
368395
padding: _kExpandIconPadding,
396+
splashColor: child.splashColor,
397+
highlightColor: child.highlightColor,
369398
onPressed: !child.canTapOnHeader
370399
? (bool isExpanded) => _handlePressed(isExpanded, index)
371400
: null,
@@ -399,6 +428,8 @@ class _ExpansionPanelListState extends State<ExpansionPanelList> {
399428
if (child.canTapOnHeader) {
400429
header = MergeSemantics(
401430
child: InkWell(
431+
splashColor: child.splashColor,
432+
highlightColor: child.highlightColor,
402433
onTap: () => _handlePressed(_isChildExpanded(index), index),
403434
child: header,
404435
),

packages/flutter/test/material/expansion_panel_test.dart

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1948,6 +1948,74 @@ void main() {
19481948
}
19491949
});
19501950

1951+
testWidgets('Ensure IconButton splashColor and highlightColor are correctly set when canTapOnHeader is false', (WidgetTester tester) async {
1952+
const Color expectedSplashColor = Colors.green;
1953+
const Color expectedHighlightColor = Colors.yellow;
1954+
1955+
await tester.pumpWidget(MaterialApp(
1956+
home: SingleChildScrollView(
1957+
child: ExpansionPanelList(
1958+
children: <ExpansionPanel>[
1959+
ExpansionPanel(
1960+
headerBuilder: (BuildContext context, bool isExpanded) {
1961+
return const ListTile(title: Text('Panel 1'));
1962+
},
1963+
body: const ListTile(title: Text('Content for Panel 1')),
1964+
splashColor: expectedSplashColor,
1965+
highlightColor: expectedHighlightColor,
1966+
),
1967+
],
1968+
),
1969+
),
1970+
));
1971+
1972+
await tester.tap(find.text('Panel 1'));
1973+
await tester.pumpAndSettle();
1974+
1975+
final IconButton iconButton = tester.widget(find.byType(IconButton).first);
1976+
expect(iconButton.splashColor, expectedSplashColor);
1977+
expect(iconButton.highlightColor, expectedHighlightColor);
1978+
});
1979+
1980+
testWidgets('Ensure InkWell splashColor and highlightColor are correctly set when canTapOnHeader is true', (WidgetTester tester) async {
1981+
const Color expectedSplashColor = Colors.green;
1982+
const Color expectedHighlightColor = Colors.yellow;
1983+
1984+
await tester.pumpWidget(MaterialApp(
1985+
home: SingleChildScrollView(
1986+
child: ExpansionPanelList(
1987+
children: <ExpansionPanel>[
1988+
ExpansionPanel(
1989+
canTapOnHeader: true,
1990+
headerBuilder: (BuildContext context, bool isExpanded) {
1991+
return Container(
1992+
padding: const EdgeInsets.all(16),
1993+
alignment: Alignment.centerLeft,
1994+
child: const Text('Panel 1'),
1995+
);
1996+
},
1997+
body: const ListTile(title: Text('Content for Panel 1')),
1998+
splashColor: expectedSplashColor,
1999+
highlightColor: expectedHighlightColor,
2000+
),
2001+
],
2002+
),
2003+
),
2004+
));
2005+
2006+
await tester.pumpAndSettle();
2007+
2008+
final Finder inkWellFinder = find.descendant(
2009+
of: find.byType(ExpansionPanelList),
2010+
matching: find.byWidgetPredicate((Widget widget) =>
2011+
widget is InkWell && widget.onTap != null)
2012+
);
2013+
2014+
final InkWell inkWell = tester.widget<InkWell>(inkWellFinder);
2015+
expect(inkWell.splashColor, expectedSplashColor);
2016+
expect(inkWell.highlightColor, expectedHighlightColor);
2017+
});
2018+
19512019
testWidgets('ExpandIcon.disabledColor uses expandIconColor color when canTapOnHeader is true', (WidgetTester tester) async {
19522020
const Color expandIconColor = Color(0xff0000ff);
19532021

0 commit comments

Comments
 (0)