Reputation: 7499
I have a simple screen with a TextField
. There is one info text above it and one below it. Those info texts are displayed only when a certain condition is met.
Minimal example:
class FooPage extends StatefulWidget {
const FooPage({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() {
return FooState();
}
}
class FooState extends State<FooPage> {
TextEditingController controller = TextEditingController();
bool show = true;
@override
void initState() {
super.initState();
controller.addListener(() {
setState(() => show = controller.text.length < 5);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
show ? const Text("hello1") : const SizedBox.shrink(),
TextField(controller: controller),
show ? const Text("hello2") : const SizedBox.shrink(),
],
),
);
}
}
The problem is that when the info texts either appear or disappear, the TextField
loses focus! If I use just one text (either of them), everything works fine.
I can solve this by wrapping the info texts with ExcludeFocus
or using autoFocus: true
on the TextField
. But I am pretty sure those are not good solutions. At least the latter one can't be :)
What is happening here? What is the proper way to solve this?
Upvotes: 4
Views: 2339
Reputation: 3552
I can't tell you why my solution works, but if you pass a GlobalKey to the TextField, it won't lose its focus.
GlobalKey globalKey = GlobalKey();
TextField(controller: controller, key: globalKey,),
Maybe something to do with this? From the docs:
Widgets that have global keys reparent their subtrees when they are moved from one location in the tree to another location in the tree. In order to reparent its subtree, a widget must arrive at its new location in the tree in the same animation frame in which it was removed from its old location in the tree.
Upvotes: 6