Flutter:鼠标移出按钮时如何关闭PopupMenu?
我编写了以下代码,实现无需点击按钮,仅鼠标悬停即可显示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默认只会在点击外部或菜单选项时关闭,不会响应鼠标移出按钮的事件。 - 推荐两种方案:
- 手动用Overlay实现菜单(更灵活可控)
- 维护两个状态:
bool _isButtonHovered = false、bool _isMenuHovered = false - 鼠标进入按钮时设置
_isButtonHovered = true,插入Overlay显示菜单;鼠标移出按钮时设置_isButtonHovered = false - 给菜单区域套上MouseRegion,鼠标进入时设
_isMenuHovered = true,移出时设_isMenuHovered = false - 在
setState或didUpdateWidget中判断,只有当!_isButtonHovered && !_isMenuHovered时,移除Overlay关闭菜单
- 维护两个状态:
- 基于PopupMenuButton改造(兼容现有代码)
- 通过PopupMenuButton的GlobalKey获取状态,调用内部的
hideMenu()方法关闭菜单 - 同样需要给菜单添加MouseRegion监听,避免鼠标刚移到菜单上就被关闭
- 修改InkWell的onHover逻辑:当
value为false时,延迟一小段时间(比如200ms)再判断,如果此时鼠标既不在按钮上也不在菜单上,再调用hideMenu() - 调用关闭方法示例:
final GlobalKey<PopupMenuButtonState> _menuKey = GlobalKey(); // 关闭菜单 _menuKey.currentState?.hideMenu();
- 通过PopupMenuButton的GlobalKey获取状态,调用内部的
- 手动用Overlay实现菜单(更灵活可控)
内容的提问来源于stack exchange,提问作者James James
相关产品推荐
相关产品推荐

