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

Flutter中TextField输入内容点击返回或收起键盘后消失求助

Flutter TextField输入内容消失问题解决方案

问题根源

你的AddNewTaskModel是ConsumerWidget,当页面因键盘收起、状态变更(比如选择日期/分类)触发重建时,若该组件被重新实例化,内部的TextEditingController会被重新初始化,导致输入内容丢失。另外,如果在父组件的build方法中直接创建AddNewTaskModel实例,每次父组件重建都会生成新的AddNewTaskModel,控制器也会被重置。


解决方案1:改用ConsumerStatefulWidget保存控制器状态

将AddNewTaskModel从ConsumerWidget改为ConsumerStatefulWidget,把TextEditingController放在State类中,这样即使组件重建,状态会被保留,控制器的输入内容也不会丢失:

class AddNewTaskModel extends ConsumerStatefulWidget {
  const AddNewTaskModel({super.key});

  @override
  ConsumerState<AddNewTaskModel> createState() => _AddNewTaskModelState();
}

class _AddNewTaskModelState extends ConsumerState<AddNewTaskModel> {
  late final TextEditingController titleController;
  late final TextEditingController descriptionController;

  @override
  void initState() {
    super.initState();
    titleController = TextEditingController();
    descriptionController = TextEditingController();
  }

  @override
  void dispose() {
    // 释放控制器资源,避免内存泄漏
    titleController.dispose();
    descriptionController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final dateProv = ref.watch(dateProvider);
    // 保留原build方法的所有UI代码,直接使用当前state中的控制器
    return Container(
      padding: const EdgeInsets.all(30),
      height: MediaQuery.of(context).size.height * 0.70,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(16),
      ),
      child: Column(
        // ... 原UI代码完全不变
      ),
    );
  }
}

解决方案2:用Riverpod Provider管理输入状态

如果你想完全依赖Riverpod管理状态,避免控制器生命周期问题,可以创建两个StateProvider来保存标题和描述的文本:

步骤1:定义Provider

在你的provider文件中添加:

final titleTextProvider = StateProvider<String>((ref) => '');
final descriptionTextProvider = StateProvider<String>((ref) => '');

步骤2:修改AddNewTaskModel代码

class AddNewTaskModel extends ConsumerWidget {
  const AddNewTaskModel({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final dateProv = ref.watch(dateProvider);
    final titleText = ref.watch(titleTextProvider);
    final descriptionText = ref.watch(descriptionTextProvider);

    return Container(
      // ... 其他UI代码不变
      child: Column(
        // ...
        TextFieldWiget(
          maxLine: 1,
          hintText: "Add New Task",
          txtController: TextEditingController(text: titleText)..addListener(() {
            // 实时同步输入内容到Provider
            ref.read(titleTextProvider.notifier).state = titleController.text;
          }),
        ),
        // ...
        TextFieldWiget(
          maxLine: 5,
          hintText: "Add Descrption",
          txtController: TextEditingController(text: descriptionText)..addListener(() {
            ref.read(descriptionTextProvider.notifier).state = descriptionController.text;
          }),
        ),
        // ... 保存按钮逻辑修改
        ElevatedButton(
          onPressed: () {
            final getRadioValue = ref.read(radioProvider);
            String category = '';

            switch (getRadioValue) {
              case 1:
                category = 'Learning';
                break;
              case 2:
                category = 'Working';
                break;
              case 3:
                category = 'General';
                break;
            }

            // 从Provider获取输入内容
            final title = ref.read(titleTextProvider);
            final description = ref.read(descriptionTextProvider);
            print(title + 'title provider');
            print(ref.read(dateProvider));
          },
          child: const Text('Save'),
        ),
      ),
    );
  }
}

额外注意事项

  • 避免在父组件的build方法中重复创建AddNewTaskModel实例,确保组件实例的稳定性。
  • 使用TextEditingController时必须调用dispose()方法释放资源,这也是方案1中使用ConsumerStatefulWidget的核心优势之一。

内容的提问来源于stack exchange,提问作者Ujang Aripin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 18:08:11