Flutter BottomSheet收起键盘后重加载旧值问题求助
问题原因
你的问题出在无状态组件的build方法执行时机:EditTask是StatelessWidget,当键盘收起时,Flutter会触发组件重建,build方法重新执行,而你在build里每次都把TextEditingController的text重置为初始传入的taskName和description,导致输入的内容被覆盖。
解决方案:改为StatefulWidget(推荐)
StatelessWidget不适合处理需要保留临时状态的场景,改成StatefulWidget后,我们可以在initState中只初始化一次控制器的初始值,后续重建不会重置输入内容。
修改后的EditTask.dart代码:
class EditTask extends StatefulWidget { final String taskName; final String description; final int index; final Function editTask; const EditTask(this.taskName, this.description, this.index, this.editTask, {super.key}); @override State<EditTask> createState() => _EditTaskState(); } class _EditTaskState extends State<EditTask> { late final TextEditingController taskNameController; late final TextEditingController taskDescriptionController; @override void initState() { super.initState(); // 仅在组件初始化时设置一次初始值 taskNameController = TextEditingController(text: widget.taskName); taskDescriptionController = TextEditingController(text: widget.description); } @override void dispose() { // 销毁控制器,避免内存泄漏 taskNameController.dispose(); taskDescriptionController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ TextField( controller: taskNameController, decoration: const InputDecoration( labelText: 'Task Name' ), ), TextField( controller: taskDescriptionController, decoration: const InputDecoration( labelText: 'Description' ), ), TextButton( child: const Text('Save Task'), onPressed: (){ widget.editTask(taskNameController.text, taskDescriptionController.text, widget.index); Navigator.of(context).pop(); }, ) ], ); } }
关键修改说明
- 使用
initState初始化控制器:这个方法仅在组件创建时执行一次,确保初始值只设置一次,后续重建不会覆盖输入内容。 - 添加
dispose方法销毁控制器:避免内存泄漏,这是Flutter开发的最佳实践。 - 通过
widget.访问父组件传递的参数:StatefulWidget的状态类通过widget关键字访问外部传入的属性。
可选:坚持用StatelessWidget的临时方案(不推荐)
如果你一定要保留StatelessWidget,可以添加一个标志位控制仅初始化一次控制器内容:
class EditTask extends StatelessWidget { final String taskName; final String description; final int index; final Function editTask; final TextEditingController taskNameController; final TextEditingController taskDescriptionController; bool _hasSetInitialValue = false; EditTask(this.taskName, this.description, this.index, this.editTask) : taskNameController = TextEditingController(), taskDescriptionController = TextEditingController(); @override Widget build(BuildContext context) { if (!_hasSetInitialValue) { taskNameController.text = taskName; taskDescriptionController.text = description; _hasSetInitialValue = true; } return Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ TextField( controller: taskNameController, decoration: const InputDecoration(labelText: 'Task Name'), ), TextField( controller: taskDescriptionController, decoration: const InputDecoration(labelText: 'Description'), ), TextButton( child: const Text('Save Task'), onPressed: (){ editTask(taskNameController.text,taskDescriptionController.text,index); Navigator.of(context).pop(); }, ) ], ); } }
不过这种方式不符合StatelessWidget的设计初衷,因为它引入了可变状态,建议优先使用StatefulWidget方案。
内容的提问来源于stack exchange,提问作者user2955424
相关产品推荐
相关产品推荐

