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

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,
)

Related

Flutter focus: is FocusNode the thing that has focus?

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.

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.

Prevent widget from being rebuilt

A bit of a Flutter newbie, I hope you can help with this question.
I have two widgets on the main screen of my app. the top widget is a Facebook banner ad widget, the bottom part of the screen is then taken up with a list that is populated from an web API call.
When I use the toolbar to refresh the data from the API, I am using SetState to rebuild the list etc.
However, the top widget, with the Facebook ad is also being rebuilt each time, which is not what I want.
I have seen lots of talk about Bloc Patterns etc. If sounds like a bit of overkill for what I want to do, is there an easier way to just update the list without updating the banner ad widget?
Thanks
I can think of two solutions:
move the list to a separate StatefulWidget. If setState() is now called in this widget, only the included widget will be rebuilt.
something in the direction:
class _MyWidgetState extends State<MyWidget> {
Widget _facebookBanner;
#override
void initState() {
_facebookBanner = ...;
super.initState();
}
#override
Widget build(BuildContext context) {
return Column(children: <Widget>[
_facebookBanner,
ListView(...),
]);
}
}
you should add a key property to your widget, it allows you to keep a specific widget from rebuilding when changing state.
You can define the Facebook banner as const, it won't be rebuilt when declared like that
This is an example of how to use const keyword
child: const Text('This is just an example of a const widget');
Const constructors are a great optimization for stuff that you know that won't change.

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

Flutter TextField focus rebuilds widget if keyboardType changes

Trying to build my first app on Flutter, but ran into a problem. Searched a lot, but everyone is having a bit different problems (keyboard closes, stream calls, etc.)
I try to use BLoC pattern and rxDart to listen and validate fields. Everything works well if all TextFields have same keyboardType, but I have different inputs (number, link, ...) and every time I tap on an input, keyboard is changed and that triggers Widget to rebuild.
Any way to keep my Streams intact of rebuilding a widget on keyboard change?
Edit: Actually the same happens if I use ShowDialog() on that page and close it with Navigator.of(context).pop();. I understand it's a page change and widget gets rebuilt, but how can I keep data in BLoC's streams of that widget?
Or how do I add to sinks my inputs' values after widget is rebuilt?