diff --git a/packages/flutter/lib/src/material/dropdown.dart b/packages/flutter/lib/src/material/dropdown.dart index a4a22b5455..58f59548d2 100644 --- a/packages/flutter/lib/src/material/dropdown.dart +++ b/packages/flutter/lib/src/material/dropdown.dart @@ -203,7 +203,9 @@ class _DropdownMenuRouteLayout extends SingleChildLayoutDelegate { // with which to dismiss the menu. // -- https://material.google.com/components/menus.html#menus-simple-menus final double maxHeight = math.max(0.0, constraints.maxHeight - 2 * _kMenuItemHeight); - final double width = buttonRect.width + 8.0; + // The width of a menu should be at most the view width. This ensures that + // the menu does not extend past the left and right edges of the screen. + final double width = math.min(constraints.maxWidth, buttonRect.width + 8.0); return new BoxConstraints( minWidth: width, maxWidth: width, @@ -225,9 +227,7 @@ class _DropdownMenuRouteLayout extends SingleChildLayoutDelegate { } return true; }); - - final double width = buttonRect.width + 8.0; - return new Offset(buttonRect.left.clamp(0.0, size.width - width), menuTop); + return new Offset(buttonRect.left.clamp(0.0, size.width - childSize.width), menuTop); } @override diff --git a/packages/flutter/test/material/dropdown_test.dart b/packages/flutter/test/material/dropdown_test.dart index fbeac1bda6..22f451943d 100644 --- a/packages/flutter/test/material/dropdown_test.dart +++ b/packages/flutter/test/material/dropdown_test.dart @@ -164,6 +164,41 @@ void main() { expect(value, equals('two')); }); + testWidgets('Dropdown in ListView', (WidgetTester tester) async { + // Regression test for https://github.com/flutter/flutter/issues/12053 + // Positions a DropdownButton at the left and right edges of the screen, + // forcing it to be sized down to the viewport width + final String value = 'foo'; + final UniqueKey itemKey = new UniqueKey(); + await tester.pumpWidget( + new MaterialApp( + home: new Material( + child: new ListView( + children: [ + new DropdownButton( + value: value, + items: >[ + new DropdownMenuItem( + key: itemKey, + value: value, + child: new Text(value), + ), + ], + onChanged: (_) {}, + ), + ], + ), + ), + ), + ); + await tester.tap(find.text(value)); + await tester.pump(); + final List itemBoxes = tester.renderObjectList(find.byKey(itemKey)).toList(); + expect(itemBoxes[0].localToGlobal(Offset.zero).dx, equals(0.0)); + expect(itemBoxes[1].localToGlobal(Offset.zero).dx, equals(16.0)); + expect(itemBoxes[1].size.width, equals(800.0 - 16.0 * 2)); + }); + testWidgets('Dropdown screen edges', (WidgetTester tester) async { int value = 4; final List> items = >[];