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

Posted

技术标签:

【中文标题】选择项目后如何不关闭 PopUpMenuButton?【英文标题】:How not to dismiss a PopUpMenuButton after selecting an item? 【发布时间】:2020-08-12 04:18:05 【问题描述】:

我正在使用颤振的 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);
  

【问题讨论】:

【参考方案1】:

创建一个自定义类,比如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: ...),
    ];
  ,
)

【讨论】:

如何在有状态小部件中使用它来更新显示?例如,带有复选框列表的菜单。用户单击复选框,值从开/关切换并在屏幕上更新? @James 肯定不是 cmets 可以解释的。 @James 您还可以从从 PopupMenuItemState 扩展的自定义类中覆盖方法 buildChild() 并将 null 传递给 PopupMenuItem 的子字段。【参考方案2】:

所以我有一个必须要做的要求

使用带有可检查项目的下拉菜单创建表单域

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

    当一个项目被选中时,弹出窗口被关闭 单击复选框未更新复选框状态 单击文本未更新复选框

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

    在 PopupMenuItem 中设置 enabled = false 并使用手势侦听器为单击侦听器包装子项 使用 StatefulBuilder 更新状态 解决方案 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) ??
                  [],
            );
          

【讨论】:

完美运行。但是我面临一个问题,文本显示为灰色,因为小部件被禁用(我在弹出菜单中显示了蓝色的文本)。有没有办法覆盖弹出菜单项中的禁用行为 @RahulSingh 您是否尝试添加文本样式? 在你指出我这样做并且它有效之后。感谢您的帮助【参考方案3】:

您可以像这样使用 CheckedPopupMenuItem .. 如 Official 文档中所述

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

【讨论】:

这确实有效,但我想添加一个带有动画的自定义单选按钮,我不希望这个 CheckedPopUpMenu 按钮允许我这样做。顺便说一句,感谢您的回答.. 如果我的回答符合您的问题,请投票赞成。我知道你想实现单选按钮而不是 CheckedPopupMenu 按钮,但对于其他用户来说这将是有用的 我刚刚尝试了 CheckedPopUpmenu 按钮,它也不起作用,我不知道为什么,它只是被勾选并且菜单被关闭,我无法选择多个值【参考方案4】:

@Omi,

我遇到过类似的情况...想要一个 Popup,但不想在我选择 PopupMenuItem 时将其关闭。

我已经实现了这个:

启用→布尔 是否允许用户选择此项。 [...]

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

【讨论】:

以上是关于选择项目后如何不关闭 PopUpMenuButton?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不关闭菜单的情况下选择菜单项?

在表格视图中选择项目后无法关闭弹出框

jquery select2 如何在选择后不关闭

浓缩咖啡:为啥旋转器在选择后不关闭?

使用jquery选择后如何找到td的表头[关闭]

wpf combobox 关闭窗口后,再次调用不显示已经选择的值?