-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
While creating multi panel UI for wide screens sometimes you need to use several navigators. Root navigator and two nested navigators for each panel.
Currently PopupMenuButton as child of one of the nested navigators will use closest navigator to show popup menu items. This creates behavior different from what is expected. You can have multiple open popup menus when using multi panel UI!
I think people most often expect to see only one open popup on the screen at the same time. They expect that tapping outside of the presented popup menu will close it. This is how it works now at the case if you have one panel UI, but not in the case when utilizing multi panel UI with nested navigators.
Steps to Reproduce
- Execute
flutter runon the code sample - Tap on 3 dot icon button in the left AppBar
- Tap on 3 dot icon button in the right AppBar
Expected results:
Step2. Left popup appears
Step3. Left popup disappears
Actual results:
Step2. Left popup appears
Step3. Right popup appears, but left not disappears
My observations:
This happens because PopupMenuButton unconditionally uses closest Navigator from context.
I think that as default it should use root Navigator, but you can opt-in to use closest if needed.
internally PopupMenuButton uses showButtonMenu method that uses showMenu that has bool useRootNavigator = false argument. But currently this argument not used and it resolves to false.
Code sample
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
home: TwoPanelsHome(),
));
}
class TwoPanelsHome extends StatelessWidget {
const TwoPanelsHome({Key? key}) : super(key: key);
bool hanleOnPopPage(Route<dynamic> route, dynamic result) {
return route.didPop(result);
}
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(
child: Navigator(
onPopPage: hanleOnPopPage,
pages: [
TestScaffold('left/master1'),
TestScaffold('left/master2'),
].map((e) => MaterialPage<void>(child: e)).toList(),
),
),
Expanded(
child: Navigator(
onPopPage: hanleOnPopPage,
pages: [
TestScaffold('right/details1'),
TestScaffold('right/details2')
].map((e) => MaterialPage<void>(child: e)).toList(),
),
),
],
);
}
}
class TestScaffold extends StatelessWidget {
const TestScaffold(this.name, {Key? key}) : super(key: key);
final String name;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(name),
actions: [
PopupMenuButton<String>(
onSelected: (s) {
print(s);
},
itemBuilder: (context) => [
PopupMenuItem<String>(
child: Text('one'),
value: 'one',
),
PopupMenuItem<String>(
child: Text('two'),
value: 'two',
),
]),
],
),
body: Center(child: Text('$name\npress more menu button')),
);
}
}
Logs
[✓] Flutter (Channel stable, 2.8.0, on macOS 12.0.1 21A559 darwin-x64, locale en-RU)
• Flutter version 2.8.0 at /Users/ng/Tools/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision cf44000065 (8 days ago), 2021-12-08 14:06:50 -0800
• Engine revision 40a99c5951
• Dart version 2.15.0