showDialog bug:对话框不是从 Flutter 中的 PopupMenuButton 触发的



我无法使showDialogPopupMenuButton一起工作。在下面的例子中,有一个按钮可以触发显示对话框,还有一个弹出菜单也可以触发显示对话。

该按钮可以工作,但单击弹出菜单中的警报文本时,不会发生同样的情况。

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')));
}
}

然而,当我在它后面添加另一个showDialog块时,它就开始工作了。

showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: Text('test dialog'),
));

这不是一个bug。我记得PopupMenuItemonTap回调调用Navigator.pop来关闭Popup。在这种情况下,当您点击PopupMenuItem并调用showDialog时,对话框将立即弹出,并保持弹出窗口打开。

为了克服这个问题,你可以尝试这个解决方案:

PopupMenuItem(
child: const Text('Alert'),
onTap: () {
Future.delayed(
const Duration(seconds: 0),
() => showDialog(
context: context,
builder: (context) => const AlertDialog(
title: Text('test dialog'),
),
),
);
},
)

使用PopupMenuButton的实际功能有一种更简单的方法来实现它。

只需给你一个valuePopUpMenuItem,然后在PopupMenuButtononSelected回调中检查它,如下所示:

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',
),
],
),

通过这种方式,您将使用parent context,而不是这里提到的点击弹出的itemBuilder context。然后决定在收到该值时执行什么,例如打开对话框。

如果要使其正确键入安全,也可以使用enum而不是String作为值。

尝试以下代码:

PopupMenuItem(
value: val,
child: InkWell(
onTap: opendialog() ?? () {},
child: Container(
height: 20,
child: Row(
children: [
AppText(
text: "Text",
color: Colors.black38,
),
],
),
),
),
),

我刚刚结束了用GestureDetector包装我的PopupMenuItem孩子,并从那里利用onTap。

PopupMenuItem<int>(
enabled: true,
value: 0,
child: GestureDetector(
onTap: () {
showDialog(
context: context,
builder: (context) => const ConnectionDialog(),
);
},
child: Row(
children: [
Icon(
Icons.swap_calls,
color: Theme.of(context)
.colorScheme
.onSecondaryContainer,
),
const SizedBox(
width: 12,
),
const Text('SELECT DEVICE'),
],
),
),
),

最新更新