Skip to content

Conversation

@Renzo-Olivares
Copy link
Contributor

This PR updates selectable region so it dismisses the selection when a tap happens outside of it. This is done through the use of TapRegion and it's onTapOutside callback.

Screen.Recording.2025-10-10.at.10.12.42.AM.mov

Pre-launch Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I read the [Tree Hygiene] wiki page, which explains my responsibilities.
  • I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
  • I signed the [CLA].
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is [test-exempt].
  • I followed the [breaking change policy] and added [Data Driven Fixes] where supported.
  • All existing and new tests are passing.

@github-actions github-actions bot added a: text input Entering text in a text field or keyboard related problems framework flutter/packages/flutter repository. See also f: labels. labels Oct 10, 2025
Copy link
Contributor

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

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 a welcome enhancement to SelectableRegion, allowing selections to be dismissed by tapping outside the region. The implementation correctly uses TapRegion for this purpose. The accompanying test case effectively validates the new behavior. My review includes a minor suggestion for code consistency in text_selection.dart.

@Renzo-Olivares Renzo-Olivares force-pushed the sr-tapoutside-to-dismiss-selection branch 2 times, most recently from 9b1f032 to d8aeefa Compare October 12, 2025 09:13
@github-actions github-actions bot added the f: material design flutter/packages/flutter/material repository. label Oct 15, 2025
);
}
return TextFieldTapRegion(child: ExcludeSemantics(child: handle));
return TapRegion(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This could be extracted into SelectableRegionTapRegion, but not sure if we wanted to do that in this PR. Also instead of wrapping two TapRegions here we could just use one and have the groupId be provided.

Copy link
Contributor

Choose a reason for hiding this comment

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

Can this share the same group id as textfield so we don't create 2?

Copy link
Contributor

Choose a reason for hiding this comment

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

talked offline, this will cause textfield and selection area to share the same tap region and not unfocus one when the other receives tap

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Talked offline: I think if we used the same groupId as TextField, wouldn't we run into a situation where if we have a focused TextField and a SelectionArea in a column and we press the SelectionArea, the TextField will not lose focus because it is the same TapRegion as SelectionArea.

@Renzo-Olivares Renzo-Olivares force-pushed the sr-tapoutside-to-dismiss-selection branch from 86df217 to 64ee725 Compare October 16, 2025 04:35
@github-actions github-actions bot removed the f: material design flutter/packages/flutter/material repository. label Oct 16, 2025
@Renzo-Olivares Renzo-Olivares force-pushed the sr-tapoutside-to-dismiss-selection branch from cb0bff8 to db5486c Compare October 16, 2025 15:36
@Renzo-Olivares
Copy link
Contributor Author

This PR adds the basic default functionality. I plan to do a follow up PR making this overridable similar to EditableText though since it introduces more APIs Renzo-Olivares@0625dfc i'd like to do that separately.

Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

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

LGTM 👍. I'm glad you ended up finding this clean solution, I was worried it would be a lot more complicated!

Is this one of the things that SelectableRegion needs for parity with SelectableText by the way?

return TapRegion(
groupId: SelectableRegion,
onTapOutside: (PointerDownEvent event) {
// To match the native web behavior, this selectable region is
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this behavior the same on mobile and desktop?

Copy link
Contributor Author

@Renzo-Olivares Renzo-Olivares Oct 16, 2025

Choose a reason for hiding this comment

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

From my testing they behave the same. I also tried native frameworks like jetpack compose and macOS swift ui and this seems like it also matches the behavior. I tried iOS swift UI but it technically doesn't have a widget that let's you granularly select static text, it's Text().textSelection(.enabled) only works for macOS, and on iOS it selects everything (context menu pops up with "copy") and doesn't show selection handles or a highlight. I tried using a UITextView but sometimes it dismissed the selection and sometimes it did not, i'm not sure if this is due to the interaction between SwiftUI and UIViews so I haven't changed the existing behavior for native iOS.

Copy link
Member

Choose a reason for hiding this comment

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

I checked WinUI 3 on Windows, it also does not dismiss the text selection if you click outside of it (unless your click moves the focus).

In my initial review, I also wondered if this was correct. It might be worth updating the comment to clarify that this is indeed intentional. Maybe something like:

Tapping outside of the text selection does not dismiss it on Android, macOS, and Windows.

child: result,
return TapRegion(
groupId: SelectableRegion,
onTapOutside: (PointerDownEvent event) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the correct behavior that the text should be unselected when the user taps anywhere, including on the selection or on unselected text? I guess those parts are already handled elsewhere in the code?

Copy link
Contributor Author

@Renzo-Olivares Renzo-Olivares Oct 16, 2025

Choose a reason for hiding this comment

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

Kind of, the expectation is when tapping inside the selection area the gesture recognizers handle this. So for example for a tap inside a selection area the selection would be set to the tapped position.

await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
'flutter/lifecycle',
message,
(_) {},
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Not important, but maybe replace the _ with the type and variable name if you get a chance.

Comment on lines +265 to +266
// The selection only dismisses when unfocused if the app
// was currently active.
Copy link
Contributor

Choose a reason for hiding this comment

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

Good catch.

Comment on lines +288 to +293
// Tap just outside the top-left corner of the selectable region
// to dismiss the selection.
final Rect selectableRegionRect = tester.getRect(find.byType(SelectableRegion));
await tester.tapAt(selectableRegionRect.topLeft - const Offset(10.0, 10.0));
await tester.pump();
expect(paragraph.selections, isEmpty);
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Reading this test, I'm also curious what would happen if you tapped inside the selectableRegionRect. I think it also dismissed? Is that tested anywhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Taps inside the selectable region rect will be handled by the selectable regions gesture recognizers, a basic tap inside the selectable region will move the selection to the precise/nearest position. This should already be covered by the gesture tests in selectable_region_test.dart.

Copy link
Contributor

@chunhtai chunhtai left a comment

Choose a reason for hiding this comment

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

LGTM

);
}
return TextFieldTapRegion(child: ExcludeSemantics(child: handle));
return TapRegion(
Copy link
Contributor

Choose a reason for hiding this comment

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

talked offline, this will cause textfield and selection area to share the same tap region and not unfocus one when the other receives tap

Copy link
Member

@loic-sharma loic-sharma left a comment

Choose a reason for hiding this comment

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

LGTM!

@Renzo-Olivares Renzo-Olivares added the autosubmit Merge PR when tree becomes green via auto submit App label Oct 16, 2025
@auto-submit auto-submit bot added this pull request to the merge queue Oct 17, 2025
Merged via the queue into flutter:master with commit 2f110cc Oct 17, 2025
76 checks passed
@flutter-dashboard flutter-dashboard bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Oct 17, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Oct 17, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Oct 17, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Oct 17, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Oct 17, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Oct 18, 2025
auto-submit bot pushed a commit to flutter/packages that referenced this pull request Oct 18, 2025
Roll Flutter from a873a27309b0 to 891d7d539256 (32 revisions)

flutter/flutter@a873a27...891d7d5

2025-10-18 [email protected] Roll Skia from b4981b621a54 to 74df18176924 (1 revision) (flutter/flutter#177204)
2025-10-18 [email protected] Roll Fuchsia Linux SDK from ZHuhfPyyV-LcKDLRh... to M8WT2GMY46e_0fFho... (flutter/flutter#177200)
2025-10-18 [email protected] [material/dropdown_menu.dart] Refactor  _RenderDropdownMenuBody.computeDryLayout  (flutter/flutter#176503)
2025-10-18 [email protected] Roll Skia from 579c72d673dd to b4981b621a54 (2 revisions) (flutter/flutter#177199)
2025-10-17 [email protected] Roll Skia from 89a8bc508a7c to 579c72d673dd (15 revisions) (flutter/flutter#177194)
2025-10-17 [email protected] [test_fixes] Enable `deprecated_member_use_from_same_package`. (flutter/flutter#177183)
2025-10-17 [email protected] [a11y] fix table semantics cache for cells  (flutter/flutter#177073)
2025-10-17 [email protected] [web] Self-cleaning service worker (flutter/flutter#176834)
2025-10-17 [email protected] Manual roll Skia from 2d9df7c70b6f to 89a8bc508a7c (24 revisions) (flutter/flutter#177182)
2025-10-17 [email protected] Fixing WindowManagerTest::DialogCanNeverBeFullscreen possibly hanging (flutter/flutter#177179)
2025-10-17 [email protected] [VPAT][A11y][a11y-app] Add a text label to slider.  (flutter/flutter#177130)
2025-10-17 [email protected] Manual roll Dart SDK from a4485e5ef821 to a66f334fee2a (5 revisions) (flutter/flutter#177142)
2025-10-17 [email protected] [web][a11y] Fix the semantics tree reconstruction logic when a subtree is reparented to another node.  (flutter/flutter#177069)
2025-10-17 [email protected] `SelectableRegion` should use flutter rendered menu on the web for Android and iOS (flutter/flutter#177122)
2025-10-17 [email protected] Refactor: Convert Title widget to StatefulWidget (flutter/flutter#176010)
2025-10-17 [email protected] Bump AGP, KGP, Gradle Templates (flutter/flutter#176858)
2025-10-17 [email protected] Roll Packages from 835dccb to 3747006 (3 revisions) (flutter/flutter#177170)
2025-10-17 [email protected] Mark windows_unopt test as flakey (flutter/flutter#177173)
2025-10-17 [email protected] Tapping outside of `SelectableRegion` should dismiss the selection (flutter/flutter#176843)
2025-10-17 [email protected] Roll Fuchsia Linux SDK from _dd0Jv50H0oUI2Ad8... to ZHuhfPyyV-LcKDLRh... (flutter/flutter#177137)
2025-10-17 [email protected] Manual roll Dart to a4485e5ef821 (3.11.0-25.0.dev) (flutter/flutter#177132)
2025-10-17 [email protected] Make sure that a MenuAcceleratorLabel doesn't crash in 0x0 environment (flutter/flutter#176646)
2025-10-16 [email protected] Make sure that a NavigationRail doesn't crash in 0x0 environment (flutter/flutter#177022)
2025-10-16 [email protected] Make sure that a SubmenuButton doesn't crash in 0x0 environment (flutter/flutter#176535)
2025-10-16 [email protected] Fix typo in ButtonBar documentation (flutter/flutter#177078)
2025-10-16 [email protected] Make sure that an InkResponse doesn't crash in 0x0 environment (flutter/flutter#175426)
2025-10-16 [email protected] [Gradle 9] Resolve Gradle 9 Deprecations in flutter/flutter part 1 (flutter/flutter#176865)
2025-10-16 [email protected] Revert "Resolve resolve native Flutter dependencies in Android Studio (#167332)" (flutter/flutter#177053)
2025-10-16 [email protected] Manual roll Dart SDK from 2d8e0359a767 to 25b6094026e4 (5 revisions) (flutter/flutter#177109)
2025-10-16 [email protected] Add textfield prop to SearchAnchor (flutter/flutter#174497)
2025-10-16 [email protected] Fix crash when NSAttributedString is passed to insertText on macOS (flutter/flutter#176329)
2025-10-16 [email protected] Correct basque time format (flutter/flutter#177031)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC [email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
...
reidbaker pushed a commit to AbdeMohlbi/flutter that referenced this pull request Dec 10, 2025
…lutter#176843)

This PR updates selectable region so it dismisses the selection when a
tap happens outside of it. This is done through the use of `TapRegion`
and it's `onTapOutside` callback.


https://github.com/user-attachments/assets/d5678c85-9d04-4c9c-af16-9a09a001c228

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

---------

Co-authored-by: Renzo Olivares <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: text input Entering text in a text field or keyboard related problems framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants