You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中TextField输入失焦且光标错位问题求助

问题原因与修复方案

问题根源

  1. 重复创建TextEditingController:每次输入字符触发onChanged调用setState,页面重建时都会重新生成TextEditingController实例,并用当前category的文本初始化。这会导致TextField强制绑定新控制器,光标位置被重置到文本开头,同时键盘因组件重建失去焦点。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 13:20:26