Flutter中PopupMenuButton点击无法触发showDialog问题咨询
问题原因
PopupMenuItem的onTap回调执行完成后,Flutter框架会自动执行Navigator.pop操作关闭弹出的菜单。这个pop操作和你在onTap中同步执行的showDialog处于同一帧任务队列:当你调用showDialog弹出对话框后,紧接着执行的pop操作不仅会关闭菜单,还会把刚刚弹出的对话框一并关闭,所以从视觉上看就像对话框没有弹出。
你写两次showDialog能生效的原因也很简单:第一次弹出的对话框被后续的pop操作关掉了,第二次弹出的对话框没有被其他pop操作影响,所以能正常显示,这只是巧合的野路子,不建议在生产环境使用。
正确解决方案
- 方案1:使用
PopupMenuButton的onSelected回调处理点击逻辑(官方推荐)
这个回调会在菜单完全关闭之后才触发,不会和菜单的关闭pop操作冲突,示例代码如下:
PopupMenuButton( itemBuilder: (ctx) => [ const PopupMenuItem( value: "alert", child: Text('Alert'), ) ], onSelected: (value) { if(value == "alert") { showDialog( context: context, builder: (ctx) => const AlertDialog( title: Text('test dialog'), ) ); } } )
- 方案2:延迟执行
showDialog,等菜单关闭完成后再弹窗
在onTap中把showDialog的逻辑放到帧末尾执行,避开和菜单关闭的pop操作同帧执行:
PopupMenuItem( child: const Text('Alert'), onTap: () { WidgetsBinding.instance.addPostFrameCallback((_) { showDialog( context: context, builder: (ctx) => const AlertDialog( title: Text('test dialog'), ) ); }); } )
或者用Future.delayed也能达到一样的效果:
onTap: () { Future.delayed(Duration.zero, () { showDialog( context: context, builder: (ctx) => const AlertDialog(title: Text('test dialog')), ); }); }
内容的提问来源于stack exchange,提问作者kamalbanga
相关产品推荐
相关产品推荐

