From 89acdb030c6f2c13babdf0b20073ce347416259b Mon Sep 17 00:00:00 2001 From: chunhtai <47866232+chunhtai@users.noreply.github.com> Date: Wed, 6 Jan 2021 10:39:02 -0800 Subject: [PATCH] fix dropdown menu to position based on nearest navigator (#73381) --- .../flutter/lib/src/material/dropdown.dart | 4 +- .../flutter/test/material/dropdown_test.dart | 45 +++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/packages/flutter/lib/src/material/dropdown.dart b/packages/flutter/lib/src/material/dropdown.dart index aa4fea655cc..ae51b4f1df6 100644 --- a/packages/flutter/lib/src/material/dropdown.dart +++ b/packages/flutter/lib/src/material/dropdown.dart @@ -1188,8 +1188,6 @@ class _DropdownButtonState extends State> with WidgetsBindi TextStyle? get _textStyle => widget.style ?? Theme.of(context).textTheme.subtitle1; void _handleTap() { - final RenderBox itemBox = context.findRenderObject()! as RenderBox; - final Rect itemRect = itemBox.localToGlobal(Offset.zero) & itemBox.size; final TextDirection? textDirection = Directionality.maybeOf(context); final EdgeInsetsGeometry menuMargin = ButtonTheme.of(context).alignedDropdown ? _kAlignedMenuMargin @@ -1218,6 +1216,8 @@ class _DropdownButtonState extends State> with WidgetsBindi final NavigatorState navigator = Navigator.of(context); assert(_dropdownRoute == null); + final RenderBox itemBox = context.findRenderObject()! as RenderBox; + final Rect itemRect = itemBox.localToGlobal(Offset.zero, ancestor: navigator.context.findRenderObject()) & itemBox.size; _dropdownRoute = _DropdownRoute( items: menuItems, buttonRect: menuMargin.resolve(textDirection).inflateRect(itemRect), diff --git a/packages/flutter/test/material/dropdown_test.dart b/packages/flutter/test/material/dropdown_test.dart index 91725d269c6..89fced87d58 100644 --- a/packages/flutter/test/material/dropdown_test.dart +++ b/packages/flutter/test/material/dropdown_test.dart @@ -586,6 +586,51 @@ void main() { expect(itemBoxes[1].size.width, equals(800.0 - 16.0 * 2)); }); + testWidgets('Dropdown menu can position correctly inside a nested navigator', (WidgetTester tester) async { + // Regression test for https://github.com/flutter/flutter/issues/66870 + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + appBar: AppBar(), + body: Column( + children: [ + ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 500, maxHeight: 200), + child: Navigator( + onGenerateRoute: (RouteSettings s) { + return MaterialPageRoute(builder: (BuildContext context) { + return Center( + child: DropdownButton( + value: 1, + items: const >[ + DropdownMenuItem( + child: Text('First Item'), + value: 1, + ), + DropdownMenuItem( + child: Text('Second Item'), + value: 2, + ), + ], + onChanged: (_) { }, + ), + ); + }); + }, + ), + ), + ], + ), + ), + ), + ); + await tester.tap(find.text('First Item')); + await tester.pump(); + final RenderBox secondItem = tester.renderObjectList(find.text('Second Item')).toList()[1]; + expect(secondItem.localToGlobal(Offset.zero).dx, equals(150.0)); + expect(secondItem.localToGlobal(Offset.zero).dy, equals(176.0)); + }); + testWidgets('Dropdown screen edges', (WidgetTester tester) async { int? value = 4; final List> items = >[