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

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();
          },
        )
      ],
    );
  }
}
关键修改说明
  1. 使用initState初始化控制器:这个方法仅在组件创建时执行一次,确保初始值只设置一次,后续重建不会覆盖输入内容。
  2. 添加dispose方法销毁控制器:避免内存泄漏,这是Flutter开发的最佳实践。
  3. 通过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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 10:25:35