Flutter 3.7.0鼠标悬停子菜单无法持续显示的问题求助
Flutter 3.7.0 悬停子菜单无法保持显示的解决方案
问题分析
你的代码核心问题在于:当鼠标从主按钮移到子菜单时,主按钮的onHover会触发离开状态,启动延迟关闭菜单的逻辑;而子菜单的onHover调用open()的时机无法阻止这个延迟关闭,同时嵌套的TextButton会干扰菜单的事件处理,导致子菜单无法保持显示。
修复方案
通过以下几点调整解决问题:
- 用计时器统一管理菜单的关闭时机,只有当鼠标完全离开主按钮和子菜单区域一段时间后才关闭菜单
- 移除
MenuItemButton内部嵌套的TextButton,避免事件冲突 - 优化主按钮和子菜单的hover事件逻辑,联动控制计时器
修改后的完整代码
import 'package:flutter/material.dart'; import 'dart:async'; void main() => runApp(const MenuBarApp()); class MyMenuBar extends StatefulWidget implements PreferredSizeWidget { const MyMenuBar({super.key}); @override State<MyMenuBar> createState() => _MyMenuBarState(); @override Size get preferredSize => const Size.fromHeight(kToolbarHeight); } class _MyMenuBarState extends State<MyMenuBar> { final MenuController _menuController = MenuController(); Timer? _closeTimer; @override void dispose() { _closeTimer?.cancel(); super.dispose(); } // 取消关闭计时器 void _cancelCloseTimer() { if (_closeTimer?.isActive ?? false) { _closeTimer!.cancel(); } } // 启动关闭计时器(300ms后关闭菜单) void _startCloseTimer() { _cancelCloseTimer(); _closeTimer = Timer(const Duration(milliseconds: 300), () { if (_menuController.isOpen) { _menuController.close(); } }); } @override Widget build(BuildContext context) { return Row( children: [ MenuAnchor( controller: _menuController, style: const MenuStyle( backgroundColor: MaterialStatePropertyAll<Color>(Colors.black), padding: MaterialStatePropertyAll<EdgeInsets>(EdgeInsets.all(8)), ), menuChildren: _getMenus(), builder: (context, controller, child) { return TextButton( child: const Text("Home"), onPressed: () {}, onHover: (isHovered) { if (isHovered) { _cancelCloseTimer(); if (!controller.isOpen) { controller.open(); } } else { _startCloseTimer(); } }, ); }, ), ], ); } List<Widget> _getMenus() { return [ MenuItemButton( onHover: (isHovered) { if (isHovered) { _cancelCloseTimer(); } else { _startCloseTimer(); } }, onPressed: () {}, child: const Text( "About", textAlign: TextAlign.left, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500, color: Colors.white, ), ), ), ]; } } class MenuBarApp extends StatelessWidget { const MenuBarApp({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( home: Scaffold(appBar: MyMenuBar()), ); } }
关键改动说明
- 添加
Timer? _closeTimer变量,用于延迟关闭菜单,避免鼠标在主按钮和子菜单之间切换时误关闭 - 新增
_cancelCloseTimer()和_startCloseTimer()方法,统一管理计时器的启动和取消 - 主按钮的
onHover逻辑:鼠标悬停时取消计时器并打开菜单;离开时启动计时器 - 子菜单的
onHover逻辑:鼠标悬停时取消计时器;离开时启动计时器,确保只有完全离开菜单区域才关闭 - 移除
MenuItemButton内部的TextButton,直接使用Text作为子组件,避免事件穿透和冲突
内容的提问来源于stack exchange,提问作者Xela
相关产品推荐
相关产品推荐

