diff --git a/packages/flutter/lib/src/material/popup_menu.dart b/packages/flutter/lib/src/material/popup_menu.dart index a5db27efa4..afc0de1144 100644 --- a/packages/flutter/lib/src/material/popup_menu.dart +++ b/packages/flutter/lib/src/material/popup_menu.dart @@ -339,9 +339,10 @@ class PopupMenuItemState> extends State { /// the menu route. @protected void handleTap() { - widget.onTap?.call(); - + // Need to pop the navigator first in case onTap may push new route onto navigator. Navigator.pop(context, widget.value); + + widget.onTap?.call(); } @override diff --git a/packages/flutter/test/material/popup_menu_test.dart b/packages/flutter/test/material/popup_menu_test.dart index a037285242..fda95a5b4d 100644 --- a/packages/flutter/test/material/popup_menu_test.dart +++ b/packages/flutter/test/material/popup_menu_test.dart @@ -3260,6 +3260,48 @@ void main() { final Offset menuTopLeft = tester.getTopLeft(find.bySemanticsLabel('Popup menu')); expect(childBottomLeft, menuTopLeft); }); + + testWidgets('PopupmenuItem onTap should be calling after Navigator.pop', (WidgetTester tester) async { + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + appBar: AppBar( + actions: [ + PopupMenuButton( + itemBuilder: (BuildContext context) => >[ + PopupMenuItem( + onTap: () { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return const SizedBox( + height: 200.0, + child: Center(child: Text('ModalBottomSheet')), + ); + }, + ); + }, + value: 10, + child: const Text('ACTION'), + ), + ], + ), + ], + ), + ), + ), + ); + + await tester.tap(find.byType(PopupMenuButton)); + await tester.pumpAndSettle(); + + await tester.tap(find.text('ACTION')); + await tester.pumpAndSettle(); + + // Verify that the ModalBottomSheet is displayed + final Finder modalBottomSheet = find.text('ModalBottomSheet'); + expect(modalBottomSheet, findsOneWidget); + }); } class TestApp extends StatelessWidget {