You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter:鼠标移出按钮时如何关闭PopupMenu?

问题:PopupMenuButton鼠标悬停显示选项,但鼠标移出按钮时无法关闭

我编写了以下代码,实现无需点击按钮,仅鼠标悬停即可显示PopupMenuButton的选项。但存在问题:能通过该方法显示选项,却无法在鼠标移出按钮时关闭选项。

触发菜单的方法代码:

openPopUpItem2() {
    GestureDetector? detector;
    searchForGestureDetector(BuildContext element) {
      element.visitChildElements((element) {
        if (element.widget != null && element.widget is GestureDetector) {
          detector = element.widget as GestureDetector;
        } else {
          searchForGestureDetector(element);
        }
      });
    }

    searchForGestureDetector(keyList[2].currentContext!);
    detector!.onTap!();
  }

调用代码:

InkWell(
                  onHover: (value) {
                    if (value) openPopUpItem2();
                  },
                  onTap: () {},
                  child: PopupMenuButton(
                      key: keyList[2],
                      tooltip: '',
                      color: Color(0xFF262533),
                      position: PopupMenuPosition.under,
                      child: MouseRegion(
                        onEnter: (details) =>
                            setState(() => ishovering2 = true),
                        onExit: (details) => setState(() {
                          ishovering2 = false;
                        }),
                        child: Text(
                          'Blog',
                          style: TextStyle(
                            color: ishovering2 ? Colors.pink : Colors.white,
                            fontSize: 24,
                            fontFamily: 'Poppins',
                          ),
                        ),
                      ),
                      itemBuilder: (BuildContext context) => <PopupMenuEntry>[
                            PopupMenuItem(
                              child: OnHover(
                                builder: (isHovered) {
                                  final color = isHovered
                                      ? Colors.pink
                                      : const Color(0xFF262533);
                                  return ListTile(
                                    title: const Text(
                                      'Archiv',
                                      style: TextStyle(color: Colors.white),
                                    ),
                                    enabled: true,
                                    hoverColor: color,
                                    onTap: () {},
                                  );
                                },
                              ),
                            ),
                          ]),
                ),

解决思路:

  • 你当前通过查找内部GestureDetector触发onTap打开菜单的方式,依赖PopupMenuButton的内部实现,不仅不稳定,而且完全没处理菜单的关闭逻辑——PopupMenuButton默认只会在点击外部或菜单选项时关闭,不会响应鼠标移出按钮的事件。
  • 推荐两种方案:
    1. 手动用Overlay实现菜单(更灵活可控)
      • 维护两个状态:bool _isButtonHovered = false、bool _isMenuHovered = false
      • 鼠标进入按钮时设置_isButtonHovered = true,插入Overlay显示菜单;鼠标移出按钮时设置_isButtonHovered = false
      • 给菜单区域套上MouseRegion,鼠标进入时设_isMenuHovered = true,移出时设_isMenuHovered = false
      • 在setState或didUpdateWidget中判断,只有当!_isButtonHovered && !_isMenuHovered时,移除Overlay关闭菜单
    2. 基于PopupMenuButton改造(兼容现有代码)
      • 通过PopupMenuButton的GlobalKey获取状态,调用内部的hideMenu()方法关闭菜单
      • 同样需要给菜单添加MouseRegion监听,避免鼠标刚移到菜单上就被关闭
      • 修改InkWell的onHover逻辑:当value为false时,延迟一小段时间(比如200ms)再判断,如果此时鼠标既不在按钮上也不在菜单上,再调用hideMenu()
      • 调用关闭方法示例:
        final GlobalKey<PopupMenuButtonState> _menuKey = GlobalKey();
        // 关闭菜单
        _menuKey.currentState?.hideMenu();
        

内容的提问来源于stack exchange,提问作者James James

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 17:50:45