Skip to content

[RawMenuAnchor] Consider using didChangeMetrics instead of MediaQuery.sizeOf #168539

@davidhicks980

Description

@davidhicks980

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.

final Size newSize = MediaQuery.sizeOf(context);
if (_viewSize != null && newSize != _viewSize) {
// Close the menus if the view changes size.
root.close();
}
_viewSize = newSize;

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();
  }

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listc: new featureNothing broken; request for a new capabilityc: proposalA detailed proposal for a change to Flutterf: material designflutter/packages/flutter/material repository.frameworkflutter/packages/flutter repository. See also f: labels.team-designOwned by Design Languages teamtriaged-designTriaged by Design Languages team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions