-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Add TapOutsideConfiguration widget #150125
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add TapOutsideConfiguration widget #150125
Conversation
7eec31f to
d56cd0a
Compare
|
Golden file changes have been found for this pull request. Click here to view and triage (e.g. because this is an intentional change). If you are still iterating on this change and are not ready to resolve the images on the Flutter Gold dashboard, consider marking this PR as a draft pull request above. You will still be able to view image results on the dashboard, commenting will be silenced, and the check will not try to resolve itself until marked ready for review. For more guidance, visit Writing a golden file test for Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
95268c3 to
94471f9
Compare
|
Golden file changes are available for triage from new commit, Click here to view. For more guidance, visit Writing a golden file test for Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
| /// * [TapOutsideConfiguration], the inherited widget that controls how | ||
| /// [EditableText] widgets behave in a subtree. | ||
| @immutable | ||
| class TapOutsideBehavior { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TapRegion isn't only used for text, it's a generic mechanism, so at the least this should be called something else if it is only to apply to EditableText's use of TapRegion.
However, I'd encourage you to think a little broader and see if there's a way we can configure default behavior for any kind of TapRegion, not just the one that EditableText happens to use. For example, maybe there should be a special subclass of TapRegion that looks for behaviors instead of taking an onTapOutside /onTapInside functions? But maybe there's a better solution than that? Then we can change EditableText to use your solution and it will also be more generally useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @gspencergoog. Thanks for the answer.
I was thinking about more generic solution. I tried to implement it on the TapRegion level and pass groupId as parameter to defaultOnTapOutside so you could implement different behaviour for different groups. The problem with the more generic solution is that you may need more then just a PointerDownEvent event that onTapOutside from TapRegion gives you. For example, to implement default behavior of EditableText.onTapOutside you need also FocusNode and probably this will be the problem for other cases. I haven't found a solution to this. If you know any let me know and I will modify PR. Otherwise I will try to adjust naming. Is EditTextTapOutsideConfiguration ok?
|
I wonder if this could be handled by turning the tap outside behavior that happens inside of It would be implemented similar to Something like this: class EditableTextTapOutsideIntent extends Intent {
const EditableTextTapOutsideIntent({required this.focusNode, this.pointerDownEvent});
final FocusNode focusNode;
final PointerDownEvent pointerDownEvent;
}And then, in late final Map<Type, Action<Intent>> _actions = <Type, Action<Intent>>{ // already exists
// ...
EditableTextTapOutsideIntent: _makeOverridable(_EditableTextTapOutsideAction<EditableTextTapOutsideIntent>()),
// ...
};
class _EditableTextTapOutsideAction<T extends EditableTextTapOutsideIntent> extends ContextAction<T> {
const _EditableTextTapOutsideAction();
@override
Object? invoke(T intent, [BuildContext? context]) {
/// The focus dropping behavior is only present on desktop platforms
/// and mobile browsers.
switch (defaultTargetPlatform) {
case TargetPlatform.android:
case TargetPlatform.iOS:
case TargetPlatform.fuchsia:
// On mobile platforms, we don't unfocus on touch events unless they're
// in the web browser, but we do unfocus for all other kinds of events.
switch (intent.pointerDownEvent.kind) {
case ui.PointerDeviceKind.touch:
if (kIsWeb) {
intentl.focusNode.unfocus();
}
case ui.PointerDeviceKind.mouse:
case ui.PointerDeviceKind.stylus:
case ui.PointerDeviceKind.invertedStylus:
case ui.PointerDeviceKind.unknown:
intent.focusNode.unfocus();
case ui.PointerDeviceKind.trackpad:
throw UnimplementedError(
'Unexpected pointer down event for trackpad');
}
case TargetPlatform.linux:
case TargetPlatform.macOS:
case TargetPlatform.windows:
intent.focusNode.unfocus();
}
}
}And finally invoke it in void _defaultOnTapOutside(PointerDownEvent event) {
Actions.maybeInvoke(context, EditableTextTapOutsideIntent(event, widget.focusNode));
}To override it, you just define an This way it would use an existing mechanism that is already part of (fyi, I haven't tried compiling or running the above, it's just hot off the top of my keyboard) |
|
(triage) @kubatatami Do you still have plans to follow up on the feedback given above? |
|
@goderbauer Yes. I will try to follow up on the feedback early next week. |
94471f9 to
b5d2db7
Compare
|
@gspencergoog @goderbauer I changed PR to use
|
| /// Creates a [EditableTextTapOutsideIntent]. | ||
| const EditableTextTapOutsideIntent({required this.focusNode, required this.pointerDownEvent}); | ||
|
|
||
| /// The [FocusNode] that this [Intent]'s action should perform on. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| /// The [FocusNode] that this [Intent]'s action should perform on. | |
| /// The [FocusNode] that this [Intent]'s action should be performed on. |
| const TransposeCharactersIntent(); | ||
| } | ||
|
|
||
| /// An [Intent] that represents a tap outside the field. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add more description here: when is it invoked, why someone might want to invoke it or override it themselves, and a "See Also:" section with a link to Action.overridable to explain how those work. This is the public API doc that will be on the API docs site, so it is what will explain this feature.
|
Hi @kubatatami , do you still plan to come back to this pr? |
Yes. I will improve docs this week. |
|
@gspencergoog @chunhtai More description added. Please let me know if there is anything else to improve. |
gspencergoog
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
justinmc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few nits here, but there's one thing that I think we should do before merging this. In the docs for onTapOutside, can you mention the new EditableTextTapOutsideIntent? I want to make sure both APIs are discoverable and avoid confusing users that might not realize setting onTapOutside will prevent triggering EditableTextTapOutsideIntent.
…tter into tap-outside-configuration
@justinmc Done. Please let me know if there is anything else to improve. |
justinmc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍
Thank you for the quick fixes!
…ide (#162575) This PR adds an `Action` for configuring a default action of `EditableText.onTapUpOutside`. This is the equivalent to what #150125 did for `EditableText.onTapOutside`. Fixes #162212 ## 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. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --------- Co-authored-by: Victor Sanni <[email protected]>

This PR adds
TapOutsideConfigurationwhere you can define a custom default logic foronTapOutside.Custom logic can be define like this:
This PR implements also two simple
AlwaysUnfocusTapOutsideBehaviorandNeverUnfocusTapOutsideBehavior.Resolves #150123
Pre-launch Checklist
///).