From 191f86ea053225cb82b0c7047b747e214a191526 Mon Sep 17 00:00:00 2001 From: impure Date: Thu, 2 Apr 2020 13:21:04 -0400 Subject: [PATCH] Added ability to change dropdown colour manually (#52982) --- .../flutter/lib/src/material/dropdown.dart | 22 ++++++++- .../flutter/test/material/dropdown_test.dart | 45 +++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/material/dropdown.dart b/packages/flutter/lib/src/material/dropdown.dart index f4eb3421fa..fe22689fde 100644 --- a/packages/flutter/lib/src/material/dropdown.dart +++ b/packages/flutter/lib/src/material/dropdown.dart @@ -203,12 +203,14 @@ class _DropdownMenu extends StatefulWidget { this.route, this.buttonRect, this.constraints, + this.dropdownColor, }) : super(key: key); final _DropdownRoute route; final EdgeInsets padding; final Rect buttonRect; final BoxConstraints constraints; + final Color dropdownColor; @override _DropdownMenuState createState() => _DropdownMenuState(); @@ -265,7 +267,7 @@ class _DropdownMenuState extends State<_DropdownMenu> { opacity: _fadeOpacity, child: CustomPaint( painter: _DropdownMenuPainter( - color: Theme.of(context).canvasColor, + color: widget.dropdownColor ?? Theme.of(context).canvasColor, elevation: route.elevation, selectedIndex: route.selectedIndex, resize: _resize, @@ -400,6 +402,7 @@ class _DropdownRoute extends PopupRoute<_DropdownRouteResult> { @required this.style, this.barrierLabel, this.itemHeight, + this.dropdownColor, }) : assert(style != null), itemHeights = List.filled(items.length, itemHeight ?? kMinInteractiveDimension); @@ -411,6 +414,7 @@ class _DropdownRoute extends PopupRoute<_DropdownRouteResult> { final ThemeData theme; final TextStyle style; final double itemHeight; + final Color dropdownColor; final List itemHeights; ScrollController scrollController; @@ -441,6 +445,7 @@ class _DropdownRoute extends PopupRoute<_DropdownRouteResult> { elevation: elevation, theme: theme, style: style, + dropdownColor: dropdownColor, ); } ); @@ -526,6 +531,7 @@ class _DropdownRoutePage extends StatelessWidget { this.elevation = 8, this.theme, this.style, + this.dropdownColor, }) : super(key: key); final _DropdownRoute route; @@ -537,6 +543,7 @@ class _DropdownRoutePage extends StatelessWidget { final int elevation; final ThemeData theme; final TextStyle style; + final Color dropdownColor; @override Widget build(BuildContext context) { @@ -559,6 +566,7 @@ class _DropdownRoutePage extends StatelessWidget { padding: padding.resolve(textDirection), buttonRect: buttonRect, constraints: constraints, + dropdownColor: dropdownColor, ); if (theme != null) @@ -789,6 +797,10 @@ class DropdownButton extends StatefulWidget { /// The [elevation] and [iconSize] arguments must not be null (they both have /// defaults, so do not need to be specified). The boolean [isDense] and /// [isExpanded] arguments must not be null. + /// + /// The [dropdownColor] argument specifies the background color of the + /// dropdown when it is open. If it is null, the current theme's + /// [ThemeData.canvasColor] will be used instead. DropdownButton({ Key key, @required this.items, @@ -811,6 +823,7 @@ class DropdownButton extends StatefulWidget { this.focusColor, this.focusNode, this.autofocus = false, + this.dropdownColor, }) : assert(items == null || items.isEmpty || value == null || items.where((DropdownMenuItem item) { return item.value == value; @@ -1049,6 +1062,12 @@ class DropdownButton extends StatefulWidget { /// {@macro flutter.widgets.Focus.autofocus} final bool autofocus; + /// The background color of the dropdown. + /// + /// If it is not provided, the theme's [ThemeData.canvasColor] will be used + /// instead. + final Color dropdownColor; + @override _DropdownButtonState createState() => _DropdownButtonState(); } @@ -1189,6 +1208,7 @@ class _DropdownButtonState extends State> with WidgetsBindi style: _textStyle, barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel, itemHeight: widget.itemHeight, + dropdownColor: widget.dropdownColor, ); Navigator.push(context, _dropdownRoute).then((_DropdownRouteResult newValue) { diff --git a/packages/flutter/test/material/dropdown_test.dart b/packages/flutter/test/material/dropdown_test.dart index 6a78cafb40..57ff78dafc 100644 --- a/packages/flutter/test/material/dropdown_test.dart +++ b/packages/flutter/test/material/dropdown_test.dart @@ -53,6 +53,7 @@ Widget buildFrame({ FocusNode focusNode, bool autofocus = false, Color focusColor, + Color dropdownColor, }) { return TestApp( textDirection: textDirection, @@ -78,6 +79,7 @@ Widget buildFrame({ focusNode: focusNode, autofocus: autofocus, focusColor: focusColor, + dropdownColor: dropdownColor, items: items == null ? null : items.map>((String item) { return DropdownMenuItem( key: ValueKey(item), @@ -174,6 +176,41 @@ void verifyPaintedShadow(Finder customPaint, int elevation) { ); } +Future checkDropdownColor(WidgetTester tester, {Color color}) async { + const String text = 'foo'; + await tester.pumpWidget( + MaterialApp( + home: Material( + child: DropdownButton( + dropdownColor: color, + value: text, + items: const >[ + DropdownMenuItem( + value: text, + child: Text(text), + ), + ], + onChanged: (_) { }, + ), + ), + ), + ); + await tester.tap(find.text(text)); + await tester.pump(); + + expect( + find.ancestor( + of: find.text(text).last, + matching: find.byType(CustomPaint)).at(2), + paints + ..save() + ..rrect() + ..rrect() + ..rrect() + ..rrect(color: color ?? Colors.grey[50], hasMaskFilter: false) + ); +} + bool sameGeometry(RenderBox box1, RenderBox box2) { expect(box1.localToGlobal(Offset.zero), equals(box2.localToGlobal(Offset.zero))); expect(box1.size.height, equals(box2.size.height)); @@ -1774,6 +1811,14 @@ void main() { expect(find.text('Two as an Arabic numeral: 2'), findsOneWidget); }); + testWidgets('DropdownButton uses default color when expanded', (WidgetTester tester) async { + await checkDropdownColor(tester); + }); + + testWidgets('DropdownButton uses dropdownColor when expanded when given', (WidgetTester tester) async { + await checkDropdownColor(tester, color: const Color.fromRGBO(120, 220, 70, 0.8)); + }); + testWidgets('DropdownButton hint displays properly when selectedItemBuilder is defined', (WidgetTester tester) async { // Regression test for https://github.com/flutter/flutter/issues/42340 final List items = ['1', '2', '3'];