Added ability to change dropdown colour manually (#52982)

diff --git a/packages/flutter/lib/src/material/dropdown.dart b/packages/flutter/lib/src/material/dropdown.dart
index f4eb342..fe22689 100644
--- a/packages/flutter/lib/src/material/dropdown.dart
+++ b/packages/flutter/lib/src/material/dropdown.dart
@@ -203,12 +203,14 @@
     this.route,
     this.buttonRect,
     this.constraints,
+    this.dropdownColor,
   }) : super(key: key);
 
   final _DropdownRoute<T> route;
   final EdgeInsets padding;
   final Rect buttonRect;
   final BoxConstraints constraints;
+  final Color dropdownColor;
 
   @override
   _DropdownMenuState<T> createState() => _DropdownMenuState<T>();
@@ -265,7 +267,7 @@
       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 @@
     @required this.style,
     this.barrierLabel,
     this.itemHeight,
+    this.dropdownColor,
   }) : assert(style != null),
        itemHeights = List<double>.filled(items.length, itemHeight ?? kMinInteractiveDimension);
 
@@ -411,6 +414,7 @@
   final ThemeData theme;
   final TextStyle style;
   final double itemHeight;
+  final Color dropdownColor;
 
   final List<double> itemHeights;
   ScrollController scrollController;
@@ -441,6 +445,7 @@
           elevation: elevation,
           theme: theme,
           style: style,
+          dropdownColor: dropdownColor,
         );
       }
     );
@@ -526,6 +531,7 @@
     this.elevation = 8,
     this.theme,
     this.style,
+    this.dropdownColor,
   }) : super(key: key);
 
   final _DropdownRoute<T> route;
@@ -537,6 +543,7 @@
   final int elevation;
   final ThemeData theme;
   final TextStyle style;
+  final Color dropdownColor;
 
   @override
   Widget build(BuildContext context) {
@@ -559,6 +566,7 @@
       padding: padding.resolve(textDirection),
       buttonRect: buttonRect,
       constraints: constraints,
+      dropdownColor: dropdownColor,
     );
 
     if (theme != null)
@@ -789,6 +797,10 @@
   /// 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 @@
     this.focusColor,
     this.focusNode,
     this.autofocus = false,
+    this.dropdownColor,
   }) : assert(items == null || items.isEmpty || value == null ||
               items.where((DropdownMenuItem<T> item) {
                 return item.value == value;
@@ -1049,6 +1062,12 @@
   /// {@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<T> createState() => _DropdownButtonState<T>();
 }
@@ -1189,6 +1208,7 @@
       style: _textStyle,
       barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
       itemHeight: widget.itemHeight,
+      dropdownColor: widget.dropdownColor,
     );
 
     Navigator.push(context, _dropdownRoute).then<void>((_DropdownRouteResult<T> newValue) {
diff --git a/packages/flutter/test/material/dropdown_test.dart b/packages/flutter/test/material/dropdown_test.dart
index 6a78caf..57ff78d 100644
--- a/packages/flutter/test/material/dropdown_test.dart
+++ b/packages/flutter/test/material/dropdown_test.dart
@@ -53,6 +53,7 @@
   FocusNode focusNode,
   bool autofocus = false,
   Color focusColor,
+  Color dropdownColor,
 }) {
   return TestApp(
     textDirection: textDirection,
@@ -78,6 +79,7 @@
             focusNode: focusNode,
             autofocus: autofocus,
             focusColor: focusColor,
+            dropdownColor: dropdownColor,
             items: items == null ? null : items.map<DropdownMenuItem<String>>((String item) {
               return DropdownMenuItem<String>(
                 key: ValueKey<String>(item),
@@ -174,6 +176,41 @@
   );
 }
 
+Future<void> checkDropdownColor(WidgetTester tester, {Color color}) async {
+  const String text = 'foo';
+  await tester.pumpWidget(
+    MaterialApp(
+      home: Material(
+        child: DropdownButton<String>(
+          dropdownColor: color,
+          value: text,
+          items: const <DropdownMenuItem<String>>[
+            DropdownMenuItem<String>(
+              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 @@
     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<String> items = <String>['1', '2', '3'];