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
相关产品推荐
相关产品推荐

