Skip to content

Commit 191f86e

Browse files
authored
Added ability to change dropdown colour manually (flutter#52982)
1 parent 54d75a5 commit 191f86e

File tree

2 files changed

+66
-1
lines changed

2 files changed

+66
-1
lines changed

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,12 +203,14 @@ class _DropdownMenu<T> extends StatefulWidget {
203203
this.route,
204204
this.buttonRect,
205205
this.constraints,
206+
this.dropdownColor,
206207
}) : super(key: key);
207208

208209
final _DropdownRoute<T> route;
209210
final EdgeInsets padding;
210211
final Rect buttonRect;
211212
final BoxConstraints constraints;
213+
final Color dropdownColor;
212214

213215
@override
214216
_DropdownMenuState<T> createState() => _DropdownMenuState<T>();
@@ -265,7 +267,7 @@ class _DropdownMenuState<T> extends State<_DropdownMenu<T>> {
265267
opacity: _fadeOpacity,
266268
child: CustomPaint(
267269
painter: _DropdownMenuPainter(
268-
color: Theme.of(context).canvasColor,
270+
color: widget.dropdownColor ?? Theme.of(context).canvasColor,
269271
elevation: route.elevation,
270272
selectedIndex: route.selectedIndex,
271273
resize: _resize,
@@ -400,6 +402,7 @@ class _DropdownRoute<T> extends PopupRoute<_DropdownRouteResult<T>> {
400402
@required this.style,
401403
this.barrierLabel,
402404
this.itemHeight,
405+
this.dropdownColor,
403406
}) : assert(style != null),
404407
itemHeights = List<double>.filled(items.length, itemHeight ?? kMinInteractiveDimension);
405408

@@ -411,6 +414,7 @@ class _DropdownRoute<T> extends PopupRoute<_DropdownRouteResult<T>> {
411414
final ThemeData theme;
412415
final TextStyle style;
413416
final double itemHeight;
417+
final Color dropdownColor;
414418

415419
final List<double> itemHeights;
416420
ScrollController scrollController;
@@ -441,6 +445,7 @@ class _DropdownRoute<T> extends PopupRoute<_DropdownRouteResult<T>> {
441445
elevation: elevation,
442446
theme: theme,
443447
style: style,
448+
dropdownColor: dropdownColor,
444449
);
445450
}
446451
);
@@ -526,6 +531,7 @@ class _DropdownRoutePage<T> extends StatelessWidget {
526531
this.elevation = 8,
527532
this.theme,
528533
this.style,
534+
this.dropdownColor,
529535
}) : super(key: key);
530536

531537
final _DropdownRoute<T> route;
@@ -537,6 +543,7 @@ class _DropdownRoutePage<T> extends StatelessWidget {
537543
final int elevation;
538544
final ThemeData theme;
539545
final TextStyle style;
546+
final Color dropdownColor;
540547

541548
@override
542549
Widget build(BuildContext context) {
@@ -559,6 +566,7 @@ class _DropdownRoutePage<T> extends StatelessWidget {
559566
padding: padding.resolve(textDirection),
560567
buttonRect: buttonRect,
561568
constraints: constraints,
569+
dropdownColor: dropdownColor,
562570
);
563571

564572
if (theme != null)
@@ -789,6 +797,10 @@ class DropdownButton<T> extends StatefulWidget {
789797
/// The [elevation] and [iconSize] arguments must not be null (they both have
790798
/// defaults, so do not need to be specified). The boolean [isDense] and
791799
/// [isExpanded] arguments must not be null.
800+
///
801+
/// The [dropdownColor] argument specifies the background color of the
802+
/// dropdown when it is open. If it is null, the current theme's
803+
/// [ThemeData.canvasColor] will be used instead.
792804
DropdownButton({
793805
Key key,
794806
@required this.items,
@@ -811,6 +823,7 @@ class DropdownButton<T> extends StatefulWidget {
811823
this.focusColor,
812824
this.focusNode,
813825
this.autofocus = false,
826+
this.dropdownColor,
814827
}) : assert(items == null || items.isEmpty || value == null ||
815828
items.where((DropdownMenuItem<T> item) {
816829
return item.value == value;
@@ -1049,6 +1062,12 @@ class DropdownButton<T> extends StatefulWidget {
10491062
/// {@macro flutter.widgets.Focus.autofocus}
10501063
final bool autofocus;
10511064

1065+
/// The background color of the dropdown.
1066+
///
1067+
/// If it is not provided, the theme's [ThemeData.canvasColor] will be used
1068+
/// instead.
1069+
final Color dropdownColor;
1070+
10521071
@override
10531072
_DropdownButtonState<T> createState() => _DropdownButtonState<T>();
10541073
}
@@ -1189,6 +1208,7 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> with WidgetsBindi
11891208
style: _textStyle,
11901209
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
11911210
itemHeight: widget.itemHeight,
1211+
dropdownColor: widget.dropdownColor,
11921212
);
11931213

11941214
Navigator.push(context, _dropdownRoute).then<void>((_DropdownRouteResult<T> newValue) {

packages/flutter/test/material/dropdown_test.dart

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ Widget buildFrame({
5353
FocusNode focusNode,
5454
bool autofocus = false,
5555
Color focusColor,
56+
Color dropdownColor,
5657
}) {
5758
return TestApp(
5859
textDirection: textDirection,
@@ -78,6 +79,7 @@ Widget buildFrame({
7879
focusNode: focusNode,
7980
autofocus: autofocus,
8081
focusColor: focusColor,
82+
dropdownColor: dropdownColor,
8183
items: items == null ? null : items.map<DropdownMenuItem<String>>((String item) {
8284
return DropdownMenuItem<String>(
8385
key: ValueKey<String>(item),
@@ -174,6 +176,41 @@ void verifyPaintedShadow(Finder customPaint, int elevation) {
174176
);
175177
}
176178

179+
Future<void> checkDropdownColor(WidgetTester tester, {Color color}) async {
180+
const String text = 'foo';
181+
await tester.pumpWidget(
182+
MaterialApp(
183+
home: Material(
184+
child: DropdownButton<String>(
185+
dropdownColor: color,
186+
value: text,
187+
items: const <DropdownMenuItem<String>>[
188+
DropdownMenuItem<String>(
189+
value: text,
190+
child: Text(text),
191+
),
192+
],
193+
onChanged: (_) { },
194+
),
195+
),
196+
),
197+
);
198+
await tester.tap(find.text(text));
199+
await tester.pump();
200+
201+
expect(
202+
find.ancestor(
203+
of: find.text(text).last,
204+
matching: find.byType(CustomPaint)).at(2),
205+
paints
206+
..save()
207+
..rrect()
208+
..rrect()
209+
..rrect()
210+
..rrect(color: color ?? Colors.grey[50], hasMaskFilter: false)
211+
);
212+
}
213+
177214
bool sameGeometry(RenderBox box1, RenderBox box2) {
178215
expect(box1.localToGlobal(Offset.zero), equals(box2.localToGlobal(Offset.zero)));
179216
expect(box1.size.height, equals(box2.size.height));
@@ -1774,6 +1811,14 @@ void main() {
17741811
expect(find.text('Two as an Arabic numeral: 2'), findsOneWidget);
17751812
});
17761813

1814+
testWidgets('DropdownButton uses default color when expanded', (WidgetTester tester) async {
1815+
await checkDropdownColor(tester);
1816+
});
1817+
1818+
testWidgets('DropdownButton uses dropdownColor when expanded when given', (WidgetTester tester) async {
1819+
await checkDropdownColor(tester, color: const Color.fromRGBO(120, 220, 70, 0.8));
1820+
});
1821+
17771822
testWidgets('DropdownButton hint displays properly when selectedItemBuilder is defined', (WidgetTester tester) async {
17781823
// Regression test for https://github.com/flutter/flutter/issues/42340
17791824
final List<String> items = <String>['1', '2', '3'];

0 commit comments

Comments
 (0)