I am creating an app with Flutter TextField widgets:
class CategoryData {
int? id;
String name;
String description;
CategoryData({this.id, required this.name, required this.description});
}
class CategoriesEdit extends StatefulWidget {
Database? db;
CategoryData? category;
CategoriesEdit({super.key, required this.db, required this.category});
@override
State<StatefulWidget> createState() => CategoriesEditState();
}
class CategoriesEditState extends State<CategoriesEdit> {
CategoryData? category;
void saveState(BuildContext context) {
// ...
}
@override
Widget build(BuildContext context) {
if (category == null) {
setState(() {
category = widget.category ?? CategoryData(name: "", description: "");
});
}
return Scaffold(
appBar: AppBar(
leading: InkWell(
child: const Icon(Icons.arrow_circle_left),
onTap: () => Navigator.pop(context)),
title: const Text("Edit Category"),
),
body: Column(children: [
Column(key: const Key('name'), children: [
const Text("Category name:*"),
TextField(
controller: TextEditingController(text: category!.name),
onChanged: (value) {
setState(() {
category!.name = value;
});
})
]),
Column(key: const Key('description'), children: [
const Text("Description:"),
TextField(
controller: TextEditingController(text: category!.description),
onChanged: (value) {
setState(() {
category!.description = value;
});
})
]),
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
ElevatedButton(
onPressed: () => saveState(context), // passing false
child: const Text('OK'),
),
OutlinedButton(
onPressed: () => Navigator.pop(context, false),
// passing false
child: const Text('Cancel'),
),
]),
]));
}
}
But after I type a character in one of these two widgets, the cursor moves before the first character and the Android keyboard widget disappears. Why? And how to fix that bug?
I tried adding widget keys, but as you see it didn't help.
There is a lot of things going wrong here, not only the stuff mentioned in the other answer.
Move the setState in the builder into initState:
if (category == null) {
setState(() {
category = widget.category ?? CategoryData(name: "", description: "");
});
}
Don't use setState in the onChanged callback. Change:
onChanged: (value) {
setState(() {
category!.description = value;
});
}
to this:
onChanged: (value) {
category!.description = value;
}
Store the TextEditingControllers, because you have to dispose them once we dispose the state.
If you are already using TextEditingControllers, then you don't need the onChanged callback. Just take text from the controller like explained in the other answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With