I am not able to get showDialog work with PopupMenuButton. In the example below, there is a button with triggering a dialog to display and a popupmenu too triggering a dialog to display.
The button works but on clicking on the Alert text in PopupMenu, the same doesn't happen.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('showDialog bug'), actions: [
PopupMenuButton(
itemBuilder: (ctx) => [
PopupMenuItem(
child: Text('Alert'),
onTap: () {
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: Text('test dialog'),
));
})
])
]),
body: ElevatedButton(
onPressed: () {
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: Text('test dialog'),
));
},
child: Text('click me')));
}
}
However, when I add another block of showDialog subsequent to it, it starts working.
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: Text('test dialog'),
));
It's not a bug. As I remember, the onTap callback of PopupMenuItem calls Navigator.pop to close the Popup. In that case, when you tap on the PopupMenuItem and call showDialog, the Dialog will be popped immediately, and leaves the Popup open.
In order to overcome that, you may try this solution :
PopupMenuItem(
child: const Text('Alert'),
onTap: () {
Future.delayed(
const Duration(seconds: 0),
() => showDialog(
context: context,
builder: (context) => const AlertDialog(
title: Text('test dialog'),
),
),
);
},
)
There is an easier way to achieve it using the actual functionality of PopupMenuButton.
Just give a value to you PopUpMenuItem and check for it on the onSelected callback from PopupMenuButton as follows:
PopupMenuButton<String>(
onSelected: (value) async {
switch (value) {
case 'open_dialog':
return showDialog(...);
default:
throw UnimplementedError();
}
},
itemBuilder: (context) => [
const PopupMenuItem(
child: Text('Open dialog'),
value: 'open_dialog',
),
],
),
This way you will consume the parent context and not the itemBuilder context that gets popped on tap as mentioned here. Then decide what to execute when that value is received, for example, opening the dialog.
You can also use an enum instead of String as values if you want to have it properly type safe.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With