Changing RawMenuAnchor close order
Closing a `RawMenuAnchor` now triggers `onClose` and `onCloseRequested` callbacks for all descendant `RawMenuAnchor`s in a coordinated sequence.
Summary
#
Closing a RawMenuAnchor now triggers the onCloseRequested
and onClose callbacks for all descendant RawMenuAnchors.
The onCloseRequested callback is triggered top-down,
starting from the triggering RawMenuAnchor and moving to its descendants,
while the onClose callback is triggered bottom-up.
If a RawMenuAnchor is already closed,
calls to MenuController.close and MenuController.closeChildren
will not trigger the onCloseRequested callback.
Background
#
RawMenuAnchor is a low-level widget used to build custom menu systems.
Previously, a RawMenuAnchor did not automatically notify its descendants
when it was closed.
Developers were required to manually call controller.closeChildren()
within the onCloseRequested callback to trigger closure
in descendant RawMenuAnchors.
Furthermore, the onClose callback timing was inconsistent.
A parent RawMenuAnchor's onClose could be executed
before its descendants had finished closing.
The updated behavior ensures that when a parent RawMenuAnchor begins to close,
it subsequently triggers onCloseRequested for all of its
descendant RawMenuAnchors in a top-down manner.
When hideOverlay is called from within onCloseRequested to close the menu,
all descendant RawMenuAnchors will have their onClose callbacks executed
in a bottom-up order.
This means that the most recently opened RawMenuAnchor
will have its onClose callback executed first,
followed by its parent, and so on up the hierarchy.
This design allows for a coordinated closing sequence
where child RawMenuAnchors can perform necessary cleanup
before their parents finalize the closing process.
Finally, if a RawMenuAnchor is already closed,
calls to MenuController.close and MenuController.closeChildren
will not trigger the onCloseRequested callback,
preventing unnecessary callback executions.
Migration guide
#
If your code does not override the default implementation of
RawMenuAnchor.onCloseRequested or your RawMenuAnchor
does not contain submenus, no changes are required.
If you have a custom implementation of onCloseRequested
in a RawMenuAnchor containing submenus,
controller.closeChildren() is now called automatically
when the parent menu closes.
You should ensure that your implementation of onCloseRequested
still behaves correctly in this context.
Immediate calls to controller.closeChildren() within your
onCloseRequested callback are no longer necessary and should be removed.
Additionally, if your logic relied on the parent's onClose callback
firing before its descendants,
you may need to refactor your code to account for the new
bottom-up execution order.
Code before migration:
RawMenuAnchor(
controller: menuController,
onCloseRequested: (hideOverlay) {
if (!animationController.isForwardOrCompleted) {
return;
}
// Descendant submenus must be closed before the parent menu. This is now
// handled automatically, so this call is no longer necessary.
menuController.closeChildren();
animationController.reverse().whenComplete(hideOverlay);
},
onClose: () {
// This might have executed before descendants called onClose().
_handleMenuClosed();
},
// ...
)
Code after migration:
RawMenuAnchor(
controller: menuController,
onCloseRequested: (hideOverlay) {
if (!animationController.isForwardOrCompleted) {
return;
}
// menuController.closeChildren() is now called automatically.
animationController.reverse().whenComplete(hideOverlay);
},
onClose: () {
// This now executes only after all descendant submenus have called onClose().
_handleMenuClosed();
},
// ...
)
References
#API documentation:
Relevant issues:
Relevant PRs:
Unless stated otherwise, the documentation on this site reflects Flutter 3.41.2. Page last updated on 2026-03-09. View source or report an issue.