如何在选择项目后不关闭PopUpMenuButton



我正在使用flutter PopUpMenuButton。我只想当我选择菜单上的任何项目时,弹出窗口不应该被忽略,而是让我从弹出窗口中选择多个值。文档中说您可以覆盖handleTap属性,但我不清楚如何做到这一点?这是有文件记录的

///The [handleTap] method can be overridden to adjust exactly what happens when
/// the item is tapped. By default, it uses [Navigator.pop] to return the
/// [PopupMenuItem.value] from the menu route.
void handleTap() {
Navigator.pop<T>(context, widget.value);
}

创建一个自定义类,比如PopupItem,它扩展PopupMenuItem并覆盖PopupMenuItemState.handleTap方法。

class PopupItem extends PopupMenuItem {
const PopupItem({
required Widget child,
Key? key,
}) : super(key: key, child: child);
@override
_PopupItemState createState() => _PopupItemState();
}
class _PopupItemState extends PopupMenuItemState {
@override
void handleTap() {}
}

你现在可以这样使用它:

PopupMenuButton(
itemBuilder: (_) {
return [
PopupItem(child: ...),
];
},
)

所以我有一个必须的要求

创建一个带有可检查项目的下拉菜单的表单字段

所以我用PopupMenuItem创建了一个弹出菜单,但后来我遇到了3个问题

  1. 当选择一个项目时,弹出窗口被取消
  2. 单击复选框不会更新复选框状态
  3. 单击文本不会更新复选框

所以我解决了所有这些问题,这可能会帮助你们

  1. 在PopupMenuItem中设置enabled=false,并用手势监听器包装子项以用于点击监听器
  2. 使用StatefulBuilder更新状态
  3. 解决方案1也解决了这个问题

这是代码->

onTapDown: (details) async {
state.didChange(
await showMenu(
context: context,
position: RelativeRect.fromLTRB(
details.globalPosition.dx,
details.globalPosition.dy,
0,
0,
),
items: itemList.keys
.map(
(e) => PopupMenuItem(
enabled: false,
child: StatefulBuilder(
builder: (BuildContext context,
StateSetter setState) {
return GestureDetector(
onTap: () {
setState(() {
itemList[e] = !itemList[e]!;
});
},
child: Row(
children: [
Expanded(child: Text(e)),
Checkbox(
value: itemList[e],
onChanged: (i) {
setState(() {
itemList[e] = i!;
});
},
),
],
),
);
},
),
),
)
.toList(),
elevation: 8.0,
).then((value) => null) ??
[],
);
}

您可以像这样使用CheckedPopupMenuItem。。如官方文件中所述

PopupMenuButton<Commands>(
onSelected: (Commands result) {
switch (result) {
case Commands.heroAndScholar:
setState(() { _heroAndScholar = !_heroAndScholar; });
break;
case Commands.hurricaneCame:
// ...handle hurricane option
break;
// ...other items handled here
}
},
itemBuilder: (BuildContext context) => <PopupMenuEntry<Commands>>[
CheckedPopupMenuItem<Commands>(
checked: _heroAndScholar,
value: Commands.heroAndScholar,
child: const Text('Hero and scholar'),
),
const PopupMenuDivider(),
const PopupMenuItem<Commands>(
value: Commands.hurricaneCame,
child: ListTile(leading: Icon(null), title: Text('Bring hurricane')),
),
// ...other items listed here
],
)

@Omi,

我也遇到过类似的情况。。。想要一个Popup,但不希望在选择PopupMenuItem时将其取消。

我已经实现了这个:

已启用→bool是否允许用户选择此项目。[…]

我已将菜单项的enabled设置为false(在我的情况下,这是一张具有自定义UI的卡(

您必须修改软件包弹出菜单按钮。每当在菜单中选择某个内容时,菜单就会弹出。因此,您只需注释掉该小部件主文件中的Navigator.pop((即可。评论主文件中的Navigator.pop<T>(context, widget.value);

/// The handler for when the user selects the menu item.
///
/// Used by the [InkWell] inserted by the [build] method.
///
/// By default, uses [Navigator.pop] to return the [PopupMenuItem.value] from
/// the menu route.
@protected
void handleTap() {
widget.onTap?.call();
// Navigator.pop<T>(context, widget.value);
}

最新更新