Skip to content

[material_ui] Global context menu builder override - #12828

Open
matthewhendrix wants to merge 16 commits into
flutter:mainfrom
matthewhendrix:global-contextMenuBuilder-override
Open

[material_ui] Global context menu builder override#12828
matthewhendrix wants to merge 16 commits into
flutter:mainfrom
matthewhendrix:global-contextMenuBuilder-override

Conversation

@matthewhendrix

@matthewhendrix matthewhendrix commented Sep 10, 2026

Copy link
Copy Markdown

In certain Android app configurations, it is desirable to suppress the long-press context menu on text fields entirely — for example, in focused or restricted UI environments where exposing system-level UI (share sheet, app chooser dialogs) is undesirable or disruptive to the user experience.

The only option today is to pass contextMenuBuilder explicitly to every TextField and TextFormField in the codebase, which is impractical at scale. More critically, this approach does not cover Flutter's own widgets that embed TextField or TextFormField internally, such as TimePickerDialog, DatePickerDialog, DropdownMenu, or any third-party package using TextField internally. There is no way to suppress the context menu in those without forking Flutter or the package.

This PR adds a contextMenuBuilder field to TextSelectionThemeData, which widgets that use a contextMenuBuilder resolve before falling back to their default. This allows a developer to provide an override for the context menu at the MaterialApp level.

This PR address flutter/flutter#183227

Pre-Review Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

Footnotes

  1. Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. 2

@matthewhendrix matthewhendrix changed the title Global context menu builder override [material_ui] Global context menu builder override Sep 10, 2026
@github-actions github-actions Bot added p: material_ui triage-design Should be looked at in design triage labels Sep 10, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the ability to globally override the default context menu for text fields and selectable text by adding contextMenuBuilder to TextSelectionThemeData. Widgets such as SearchBar, SelectableText, TextField, and TextFormField are updated to resolve their context menu builders using this theme. Review feedback suggests making contextMenuBuilder nullable in _SearchAnchorWithSearchBar to prevent overriding the global theme, simplifying the resolution logic in SearchBar and TextFormField by delegating directly to TextField, and adding a test to verify SearchAnchor.bar respects the global theme override.

Comment thread packages/material_ui/lib/src/search_anchor.dart Outdated
Comment thread packages/material_ui/lib/src/search_anchor.dart Outdated
Comment thread packages/material_ui/lib/src/text_form_field.dart Outdated
Comment thread packages/material_ui/test/search_anchor_test.dart
…ach_anchor and text_form_field and adding a test to make sure that SearchAnchor.bar uses the global theme override for the context menu
@matthewhendrix
matthewhendrix marked this pull request as ready for review September 10, 2026 20:04

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for globally configuring the text context menu builder (contextMenuBuilder) via TextSelectionThemeData across text widgets, including SearchBar, SelectableText, TextField, and TextFormField. Review feedback points out an interpolation bug in _lerpContextMenuBuilder when transitioning between themes where one of the builders is null, and suggests a simplified implementation that correctly switches at t = 0.5.

Comment thread packages/material_ui/lib/src/text_selection_theme.dart
Comment thread packages/material_ui/lib/src/search_anchor.dart Outdated
Comment thread packages/material_ui/test/selectable_text_test.dart
Comment thread packages/material_ui/test/text_field_test.dart
…unction from seach_anchor, revert formatting changes to selectable_text_test and text_field_test
@Mairramer Mairramer added the CICD Run CI/CD label Sep 11, 2026
@Mairramer

Copy link
Copy Markdown
Contributor

@matthewhendrix I noticed a few validations are still failing, and we also need to add a changelog. Could you take a look when you have a chance? Thanks!

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Sep 11, 2026
@Mairramer Mairramer added the CICD Run CI/CD label Sep 11, 2026
Comment thread packages/material_ui/test/search_anchor_test.dart
Comment thread packages/material_ui/pending_changelogs/change_2026_09_11_1789133831528.yaml Outdated
@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Sep 11, 2026
@Mairramer Mairramer added the CICD Run CI/CD label Sep 11, 2026
@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Sep 11, 2026
@Mairramer Mairramer added the CICD Run CI/CD label Sep 12, 2026
@Mairramer

Copy link
Copy Markdown
Contributor

Overall, this looks really good! Thanks so much for your contribution!

Just a few details that need to be adjusted.

child: Padding(
padding: EdgeInsets.zero,
child: TextField(key: key, controller: controller, contextMenuBuilder: null),
child: TextField(key: key, controller: controller),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like contextMenuBuilder: null was removed here because passing null was falling back to the default menu with the new ?? logic. If we apply the identity comparison fix suggested in text_field.dart, we can restore contextMenuBuilder: null here and properly test that the menu is hidden.

enableInlinePrediction: widget.enableInlinePrediction,
contentInsertionConfiguration: widget.contentInsertionConfiguration,
contextMenuBuilder: widget.contextMenuBuilder,
contextMenuBuilder:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously, it defaulted to _defaultContextMenuBuilder. If a user wanted to completely disable the context menu, they could explicitly pass contextMenuBuilder: null. In the old implementation, null was passed directly to EditableText, which correctly disabled the menu.

Maybe we could do something like this:

contextMenuBuilder: widget.contextMenuBuilder == _defaultContextMenuBuilder
    ? (TextSelectionTheme.of(context).contextMenuBuilder ??
        _defaultContextMenuBuilder)
    : widget.contextMenuBuilder,

This keeps the explicit null behavior while allowing the theme to override the default builder.

this.enableIMEPersonalizedLearning = true,
this.enableInlinePrediction,
this.contextMenuBuilder = _defaultContextMenuBuilder,
this.contextMenuBuilder,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should keep the default value here to differentiate between an omitted parameter and an explicit null.

this.contextMenuBuilder = _defaultContextMenuBuilder,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD p: material_ui triage-design Should be looked at in design triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants