Flutter中TextField输入失焦且光标错位问题求助
问题原因与修复方案
问题根源
- 重复创建
TextEditingController:每次输入字符触发onChanged调用setState,页面重建时都会重新生成TextEditingController实例,并用当前category的文本初始化。这会导致TextField强制绑定新控制器,光标位置被重置到文本开头,同时键盘因组件重建失去焦点。 build方法内调用setState:在build中执行setState会触发额外的不必要重建,进一步加剧组件状态混乱。
修复代码
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; // 声明控制器为State成员变量 late TextEditingController _nameController; late TextEditingController _descriptionController; void saveState(BuildContext context) { // ... } @override void initState() { super.initState(); // 在initState中完成category初始化,避免build内触发额外重建 category = widget.category ?? CategoryData(name: "", description: ""); // 初始化控制器并绑定初始文本 _nameController = TextEditingController(text: category!.name); _descriptionController = TextEditingController(text: category!.description); } @override void dispose() { // 销毁控制器,防止内存泄漏 _nameController.dispose(); _descriptionController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { 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: _nameController, // 使用成员变量控制器 onChanged: (value) { setState(() { category!.name = value; }); }) ]), Column(key: const Key('description'), children: [ const Text("Description:"), TextField( controller: _descriptionController, // 使用成员变量控制器 onChanged: (value) { setState(() { category!.description = value; }); }) ]), Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ElevatedButton( onPressed: () => saveState(context), child: const Text('OK'), ), OutlinedButton( onPressed: () => Navigator.pop(context, false), child: const Text('Cancel'), ), ]), ])); } }
额外优化(可选)
如果需要让category和控制器文本保持自动同步,可以给控制器添加监听,去掉onChanged回调:
@override void initState() { super.initState(); category = widget.category ?? CategoryData(name: "", description: ""); _nameController = TextEditingController(text: category!.name); _descriptionController = TextEditingController(text: category!.description); // 监听控制器文本变化,自动更新category _nameController.addListener(() { setState(() { category!.name = _nameController.text; }); }); _descriptionController.addListener(() { setState(() { category!.description = _descriptionController.text; }); }); }
内容的提问来源于stack exchange,提问作者porton
相关产品推荐
相关产品推荐

