Flutter focus: is FocusNode the thing that has focus? - flutter

In the focus system, there are a lot of widgets such as Focus, FocusNode, FocusScope, FocusScopeNode, etc. I'm trying to understand the focus system and have two specific questions:
Is a FocusNode the thing that is considered to be in focus? I know that FocusScopeNode has a hasFocus but it's not as if you can focus on a FocusScopeNode because you'd actually be focusing on it's FocusNode?
Is calling .requestFocus() or .unfocus() of a FocusNode the only way that focus will be removed or given to a FocusNode? (except for autofocus) In other words, things won't automatically be focused by clicking, tapping, or hitting TAB on them?

In the Flutter framework's focus system, a FocusNode is a representation of the focus state for a particular widget or group of widgets. When a FocusNode has focus, it means that it is currently the widget that is responding to keyboard events and other forms of input focus.
A FocusScopeNode is a widget that is used to create a scope within the focus tree. A scope defines a new node in the focus tree, and all FocusNodes within that scope are descendants of that scope's node. A FocusScopeNode also has a hasFocus property, which indicates whether any of the FocusNodes within its scope currently has focus.
To answer your first question, a FocusNode is considered to be in
focus when its hasFocus property is set to true. A FocusScopeNode is
not something that can be focused on directly, but rather it is a
way of organizing the focus tree and determining which nodes are
within a particular scope.
To answer your second question, calling requestFocus() or unfocus()
on a FocusNode is not the only way to remove or give focus to a
FocusNode. In Flutter, focus can also be changed by clicking or
tapping on a widget, or by using the TAB key to navigate through the
focus tree. However, these methods of changing focus will only work
if the FocusNode is part of the focus tree and is attached to a
widget that is part of the widget hierarchy.

Related

What is the difference between setting autofocus to true and to request focus?

I read in documentation that requestFocus() request primary focus. Does setting autofocus to true behaves similarly?
When set auto focus true, whenever state will build or re-build focus will automatic shift to that element if any other elements are not holding focus, while if you are calling requestFocus this will set primary focus to that
particular focus node.
Note- if you are calling FocusNode().requestFocus() that will remove focus form that screen because FocusNode() is not associated with any widget in tree

Text getting cleared when using TextEditingController and StreamBuilder

I have observed some strange behaviour when using TextEditingController and FocusNode in combination with StreamBuilder, namely:
Text inside a TextField getting cleared when unselecting the text field
Two input carets being active at the same time on two separate text fields
This happens when all the following conditions are met:
A stateless widget creates its own TextEditingControllers and FocusNodes.
These are used within some TextField widgets.
The stateless widget's build method returns a StreamBuilder, which rebuilds the widget contents (including the TextFields) when new values are pushed to the stream.
The stateless widget is presented as a MaterialPageRoute.
NOTE: if the stateless widget is not presented, but is presented directly when the app starts, the issue does not appear.
The problem was on my end. The issue was that I was persisting objects inside a StatelessWidget.
You shouldn't.
Opening the keyboard tends to rebuild the whole screen (which is fine). But in my case rebuilding cause your TextEditingController to be GCed because you stored them inside a StatelessWidget
So the reason that this works with StatefulWidget is that the state is retained even across rebuilds, so I can use it to hold my TextEditingControllers.

Auto Scroll in an empty field during validation in flutter

I have created a form in flutter and during validation (when clicking on the button) I want it to scroll up to the empty field. I have tried many ways including FocusNode and because there are many textfields, its not working. I think I am doing it the wrong way. Can someone help?
create a diffrent focusNode for each TextFormField and then
call requestFocus() on the Node when the validation is false.
first some where
final FocusNode d = FocusNode();
then in the TextFormField Widegt
focusNode: d
then in your validat
d.requestFocus();
and redo that for every TextField and not forget to check for the currect Text Field in the validator

Choosing StatelessWidget or StatefulWidget for sub-widget which has TextEditingController as a child

I'm working on a refactored code to separated small piece of widgets.
There's several columns with TextFields in each one of them.I have two options to complete the task :
Choosing StatelessWidget since it have more performance, may put TextEditingController related code outside of sub widgets. Or include some logic in onChanged event. but still there's some events like clear text can't put in onChanged event
Choosing StatefulWidget if I use TextEditingController include inside each sub widget.
How to choose between StatelessWidget and StatefulWidget when refactoring code into small widgets like this ?
Update
Here's my current conclusion which can be updated if it's not correct.
Prefer to put FocusNode of TextEditin parent since it's related to brother focusNode & parentNode;
Prefer to put TextEdtingController in parent, which will be useful in cases like when TextField is out of screen like a ListItem scrolled out of the screen, which will make the whole widget unmounted. The state will be preserved.
Preferring to put animation self like shaking TextField when inputting something wrong in self. Since it's a feature of the TextField not related to the parent.
Edit in response to the discussion in the comments section:
You should go with the second approach when refactoring your code into smaller StatefulWidgets. And the parent should have a function to alter the nested TextFields' content and its animation behavior by calling functions inside it, as you earlier indicated you need to manage this behavior.

AutoFocus isn't working in multiple Stateful widgets within a PageView

So I have 5 pages in a series of "steps" to complete an action. This is all fine and dandy. I am using a PageView with the various children pages.
The issue -- is that only the first page (that has an autofocus on a TextField widget) is actually getting the focus. As the user traverses the other form type pages -- even though there is an autofocus: true on each page .. they aren't being fired and no focus is being set at all.
This is confusing behavior to me. Each page is being rendered "on the fly" (and destroyed) when going from page to page .. so not sure why the focus isn't being set.
The general widget tree is
Scaffold
PageView
[children pages]
So maybe it has something to do with the focus being at the Scaffold context level and thus .. ah.. well I have no idea actually.. I would think when children page 2 that has an autofocus -- would -- set the overall context autofocus again when it's built?
Rather confused -- help appreciated!
Cheers!
I have had the same issue and solved it using focus node.
In my case all the children of pageView were Stateful widget each
Solution:
final FocusNode _focusNode = FocusNode();
#override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) =>FocusScope.of(context).requestFocus(_focusNode));
}
Than in Your Widget
child: TextFormField(
focusNode: _focusNode,
)