-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
Use case
When RawMenuAnchor closes on view size changes, we are currently triggering menu closure from didChangeDependencies using MediaQuery.sizeOf(context). Doing so triggers a build during SchedulerPhase.persistentCallbacks. While building during persistent callbacks normally throws an error, there are several areas in the RawMenuAnchor code where the SchedulerPhase is guarded to determine whether setState and OverlayController.show() should be called immediately or in a post-frame callback. This prevents errors, but also complicates the behavior of RawMenuAnchor.
I realized today that WidgetsBindingObserver.didChangeMetrics is called in the idle phase instead of during persistent callbacks, so switching from MediaQuery.sizeOf() to WidgetsBindingObserver.didChangeMetrics could avoid all of this phase checking. The downside is that the menu won't close if a user adds a MediaQuery widget above the menu.
flutter/packages/flutter/lib/src/widgets/raw_menu_anchor.dart
Lines 337 to 342 in 71c847e
| final Size newSize = MediaQuery.sizeOf(context); | |
| if (_viewSize != null && newSize != _viewSize) { | |
| // Close the menus if the view changes size. | |
| root.close(); | |
| } | |
| _viewSize = newSize; |
flutter/packages/flutter/lib/src/widgets/raw_menu_anchor.dart
Lines 384 to 397 in 71c847e
| void _childChangedOpenState() { | |
| _parent?._childChangedOpenState(); | |
| if (SchedulerBinding.instance.schedulerPhase != SchedulerPhase.persistentCallbacks) { | |
| setState(() { | |
| // Mark dirty now, but only if not in a build. | |
| }); | |
| } else { | |
| SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) { | |
| setState(() { | |
| // Mark dirty | |
| }); | |
| }); | |
| } | |
| } |
Proposal
To fix the phase checks, we would just need to close RawMenuAnchor when didChangeMetrics is called:
@override
void didChangeMetrics() {
super.didChangeMetrics();
root.close();
}