flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
164.94k stars 27.18k forks source link

[Proposal]Tapping a virtual keyboard's next-button, when in a text-field should not switch focus to other widgets apart from TextField #95975

Open marcglasberg opened 2 years ago

marcglasberg commented 2 years ago

If a TextField has textInputAction: TextInputAction.next, a right-arrow will be displayed in the virtual keyboard in the Android phone.

If next to that TextField there is another TextField, pressing that right-arrow will move focus to that other TextField, which is the correct expected behavior.

However, if next to that TextField there is, say, a button; then pressing that right-arrow will move focus to that button, which makes no sense in a phone.

I don't understand why, in phones (Android and iOS), widgets other than textfields can have focus. There's nothing we can do with that focus.

It makes perfect sense in the desktop or web, of course.

So my questions are:

1) Does it make sense that widgets other than textfields can have focus, in phones?

2) Without having to manually add ExcludeFocus everywhere, how do I prevent focus of non-textfields in phones, so that pressing the abovementioned right-arrow will move focus to the next text-field?

This issue is to suggest that non-textfield widgets should detect the platform, and accept focus only for desktop/web.

willlockwood commented 2 years ago
  1. Does it make sense that widgets other than textfields can have focus, in phones?

I'm no expert on the focus system, but my understanding is that this is a useful thing in part so that mobile apps can be configured to be navigable by hardware keyboards. Let's say you have a mobile app whose main purpose is to collect customer data in forms, and it's running on an iPad that's hooked up to a physical keyboard. Ideally you should be able to configure the app to have all the fields be navigable with tabs, and then at the end, be able to focus a submit button and press enter to click it.

  1. Without having to manually add ExcludeFocus everywhere, how do I prevent focus of non-textfields in phones, so that pressing the abovementioned right-arrow will move focus to the next text-field?

I think you might be looking for FocusNode.skipTraversal?: https://api.flutter.dev/flutter/widgets/FocusNode/skipTraversal.html

I can think of a few other ways to get around this if you want it more immediately baked into your app's components, but my understanding is that setting skipTraversal to true on your own provided FocusNode will prevent it from being focused when navigating through the focus tree.

marcglasberg commented 2 years ago

Mobile devices almost never have keyboards, so giving focus to buttons in mobile devices should never be the default behavior. But I'd agree that, more precisely, a widget should only gain focus if there is a keyboard connected to itself when it has focus, whatever keyboard it may be. Which in mobile devices means removing focus from non-textfields, unless there is a physical keyboard.

No, FocusNode.skipTraversal is not what I want. Having to add FocusNode.skipTraversal everywhere is an even greater amount of work as having to add ExcludeFocus everywhere. And FocusNode.skipTraversal still lets the non-textfields gain focus in other ways, which is not useful at all.

My point is simple: Tapping the keyboard next-button when in a text-field and having the focus end up in a button (or checkbox, or radiobutton etc) in a mobile device with no physical keyboard makes no sense. The virtual keyboard will just close, and the button will change color, get focus, but there is no way for the user to do anything with that.

willlockwood commented 2 years ago

Gotcha, ok understood. I'll let someone else (maybe someone actually on the team) weigh in on the framework design there 👍🏻

maheshj01 commented 2 years ago

Hi @marcglasberg, Thanks for filing the issue. I believe there are many use cases where you want to programmatically focus on widgets, One main use case I can think of is the Accessibility feature (Talkback in Android or VoiceOver on IOS) where swiping left or right the focus shifts on different widgets and double-tap anywhere onscreen simulates a tap on the currently focused widget. Also when mobile phones are connected with other I/O devices e.g joystick or physical keyboard focus is required. In case you don't want a particular widget or part of a widget tree to gain focus you may wrap it in ExcludeFocus, I am not sure if there is any other way apart from this. But I believe its just a few lines of code to remove focus on widgets which wouldn't make a difference.

marcglasberg commented 2 years ago

@maheshmnj Yes, you are right, we should be allowed to programmatically focus on widgets.

This discussion has shown me that there are a lot of use cases where you do want those non-text-field widgets to actually get focus. I changed this issue's description to: Tapping a VIRTUAL keyboard's next-button, when in a text-field, should move us to the next text-field.

This is not something for the app developer to deal with. You said "In case you don't want a particular widget or part of a widget tree to gain focus"... But it's not that I want or don't want some widgets to get focus. Nobody would want a button to get focus after a next button is pressed on a virtual keyboard, because the keyboard will close, and that's a dead end.

It remains true that 99% of the time you are in Android/iOS, the keyboard is virtual, and no accessibility feature is being used. So, most of the time, overwhelmingly, having the focus end up in a button (or checkbox, or radiobutton etc) in a mobile device with no physical keyboard makes no sense at all.

Doing the right thing here can and should be automatic.

maheshj01 commented 2 years ago

But it's not that I want or don't want some widgets to get focus. Nobody would want a button to get focus after a next button is pressed on a virtual keyboard, because the keyboard will close, and that's a dead end.

Thanks for the info @marcglasberg, This does seem like a plausible proposal. I will leave this open for further thoughts from the team.