Skip to content

Commit 3e069a4

Browse files
authored
fix issue flutter#55400 PopupMenuButton positions menu incorrectly with nest… (flutter#65832)
1 parent 7ce0dce commit 3e069a4

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1077,7 +1077,7 @@ class PopupMenuButtonState<T> extends State<PopupMenuButton<T>> {
10771077
void showButtonMenu() {
10781078
final PopupMenuThemeData popupMenuTheme = PopupMenuTheme.of(context);
10791079
final RenderBox button = context.findRenderObject()! as RenderBox;
1080-
final RenderBox overlay = Overlay.of(context)!.context.findRenderObject()! as RenderBox;
1080+
final RenderBox overlay = Navigator.of(context)!.overlay!.context.findRenderObject()! as RenderBox;
10811081
final RelativeRect position = RelativeRect.fromRect(
10821082
Rect.fromPoints(
10831083
button.localToGlobal(widget.offset, ancestor: overlay),

packages/flutter/test/material/popup_menu_test.dart

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,89 @@ void main() {
634634
await testPositioningDownThenUp(tester, TextDirection.rtl, Alignment.bottomCenter, TextDirection.rtl, const Rect.fromLTWH(450.0, 500.0, 0.0, 0.0));
635635
});
636636

637+
testWidgets('PopupMenu positioning inside nested Overlay', (WidgetTester tester) async {
638+
final Key buttonKey = UniqueKey();
639+
640+
await tester.pumpWidget(
641+
MaterialApp(
642+
home: Scaffold(
643+
appBar: AppBar(title: const Text('Example')),
644+
body: Padding(
645+
padding: const EdgeInsets.all(8.0),
646+
child: Overlay(
647+
initialEntries: <OverlayEntry>[
648+
OverlayEntry(
649+
builder: (_) => Center(
650+
child: PopupMenuButton<int>(
651+
key: buttonKey,
652+
itemBuilder: (_) => <PopupMenuItem<int>>[
653+
const PopupMenuItem<int>(value: 1, child: Text('Item 1')),
654+
const PopupMenuItem<int>(value: 2, child: Text('Item 2')),
655+
],
656+
child: const Text('Show Menu'),
657+
),
658+
),
659+
),
660+
],
661+
),
662+
),
663+
),
664+
),
665+
);
666+
667+
final Finder buttonFinder = find.byKey(buttonKey);
668+
final Finder popupFinder = find.bySemanticsLabel('Popup menu');
669+
await tester.tap(buttonFinder);
670+
await tester.pumpAndSettle();
671+
672+
final Offset buttonTopLeft = tester.getTopLeft(buttonFinder);
673+
expect(tester.getTopLeft(popupFinder), buttonTopLeft);
674+
});
675+
676+
testWidgets('PopupMenu positioning inside nested Navigator', (WidgetTester tester) async {
677+
final Key buttonKey = UniqueKey();
678+
679+
await tester.pumpWidget(
680+
MaterialApp(
681+
home: Scaffold(
682+
appBar: AppBar(title: const Text('Example')),
683+
body: Padding(
684+
padding: const EdgeInsets.all(8.0),
685+
child: Navigator(
686+
onGenerateRoute: (RouteSettings settings) {
687+
return MaterialPageRoute<dynamic>(
688+
builder: (BuildContext context) {
689+
return Padding(
690+
padding: const EdgeInsets.all(8.0),
691+
child: Center(
692+
child: PopupMenuButton<int>(
693+
key: buttonKey,
694+
itemBuilder: (_) => <PopupMenuItem<int>>[
695+
const PopupMenuItem<int>(value: 1, child: Text('Item 1')),
696+
const PopupMenuItem<int>(value: 2, child: Text('Item 2')),
697+
],
698+
child: const Text('Show Menu'),
699+
),
700+
),
701+
);
702+
},
703+
);
704+
},
705+
),
706+
),
707+
),
708+
),
709+
);
710+
711+
final Finder buttonFinder = find.byKey(buttonKey);
712+
final Finder popupFinder = find.bySemanticsLabel('Popup menu');
713+
await tester.tap(buttonFinder);
714+
await tester.pumpAndSettle();
715+
716+
final Offset buttonTopLeft = tester.getTopLeft(buttonFinder);
717+
expect(tester.getTopLeft(popupFinder), buttonTopLeft);
718+
});
719+
637720
testWidgets('PopupMenu removes MediaQuery padding', (WidgetTester tester) async {
638721
late BuildContext popupContext;
639722

0 commit comments

Comments
 (0)