I am building a menu system in Flutter, and I have encountered an issue where my menu does not close when I click on a button inside the UI. However, if I set the anchorTapClosesMenu property to true (deprecated feature), the menu closes correctly when clicking on a blank area
Initially, I was using PopupMenuButton, but it didn’t work well with submenus and it had some ugly padding. The documentation suggested migrating to MenuAnchor, so I switched to that approach. I also saw an example with a submenu in the MenuAnchor documentation, which convinced me that it would be a good fit for my use case.
What I Tried:
I am using a MenuController with MenuAnchor to control the menu state. I want to close the menu when clicking anywhere outside, but I am unable to make it close when clicking on UI buttons. I tried using a GestureDetector with the onTapDown method to handle tap events. However, this prevents the UI behind the menu from receiving tap events, which interferes with normal behavior. I considered using a flag to ignore events but still allow for the UI to behave correctly, but HitTestBehavior.translucent or IgnorePointer don't work as expected.
Additional Context:
I'm trying to implement this feature in Flutter Web to mimic a standard context menu with sub-menus.
I tried debugging the menu package itself for a long time, trying to understand why the menu behaves unexpectedly, and found that the menu might be immediately reopening whenever I click on the UI. It seems like the package detects clicking on the UI as being inside the tap region, which prevents the menu from closing when clicking on UI elements.
Also, I didn't really see how to connect the menu area and the widgets in my code As a result, I tried by using Riverpod, where the menu is wrapping my entire app UI to use the full UI as the anchor and allowing me to use riverpod to call the controller's method
Code Snippets:
class MenuState {
final List<Widget> menuItems;
MenuState({required this.menuItems});
}
class MenuStateNotifier extends StateNotifier<MenuState> {
final MenuController menuController;
MenuStateNotifier(this.menuController) : super(MenuState(menuItems: []));
void openWebMenu(Offset position, List<Widget> items) {
state = MenuState(menuItems: items);
if (menuController.isOpen) {
menuController.close();
} else {
menuController.open(position: position);
}
}
}
final menuStateProvider = StateNotifierProvider<MenuStateNotifier, MenuState>((ref) {
return MenuStateNotifier(MenuController());
});
What's written in the menuAnchor documentation is to use a GestureDetector to close the menu but that prevents any event from going through
void _handleTapDown(TapDownDetails details) {
if (_menuController.isOpen) {
_menuController.close();
return;
}
// Additional logic for opening the menu
switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
case TargetPlatform.macOS:
if (HardwareKeyboard.instance.logicalKeysPressed.contains(LogicalKeyboardKey.controlLeft) ||
HardwareKeyboard.instance.logicalKeysPressed.contains(LogicalKeyboardKey.controlRight)) {
_menuController.open(position: details.localPosition);
}
break;
}
}
Riverpod Menu Integration:
class RiverPodMenu extends ConsumerStatefulWidget {
final Widget child;
const RiverPodMenu({super.key, required this.child});
@override
ConsumerState<ConsumerStatefulWidget> createState() => _RiverPodMenuState();
}
class _RiverPodMenuState extends ConsumerState<RiverPodMenu> {
@override
Widget build(BuildContext context) {
final menuNotifier = ref.watch(menuStateProvider.notifier);
final menuState = ref.watch(menuStateProvider);
return MenuAnchor(
anchorTapClosesMenu: true, // Deprecated flag but works for outside clicks
controller: menuNotifier.menuController,
menuChildren: menuState.menuItems,
child: widget.child,
);
}
}
Menu state:
The menu currently closes only when clicking on a blank area, relying on a deprecated feature. Using a GestureDetector to intercept tap events prevents the UI behind the menu from receiving interactions.
Questions:
- Why does the menu close when clicking outside but not when clicking on UI buttons?
- Can parent and child GestureDetector widgets trigger simultaneously?
- How can I close the menu when interacting with UI elements while still allowing them to function?
- Is there a better approach to managing and communicating with this type of menu across the app, especially when the widget that triggers the menu is deeply nested?
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744720745a4589894.html
评论列表(0条)