Flutter ModalBottomSheet中TextField切换点击时输入值自动消失问题
问题原因
你遇到的输入内容丢失问题核心原因如下:
newUsers被声明为 无状态组件(StatelessWidget),但内部持有了TextEditingController可变状态。切换TextField触发键盘弹出/收起时会触发界面重绘,无状态组件会被重新构建,内部声明的控制器会被重新初始化,之前存储的输入内容就会丢失。- 无状态组件没有生命周期管理,控制器使用完无法正常释放,还存在内存泄漏风险。
修复方案
将 newUsers 改造为有状态组件(StatefulWidget),把控制器、提交逻辑都放到State类中维护,同时添加控制器的释放逻辑,修改后的new_user.dart代码如下:
import 'package:flutter/material.dart'; // 类名建议符合Dart命名规范,首字母大写,改为NewUsers class NewUsers extends StatefulWidget { final Function addNewUser; const NewUsers(this.addNewUser, {super.key}); @override State<NewUsers> createState() => _NewUsersState(); } class _NewUsersState extends State<NewUsers> { final nameInputController = TextEditingController(); final marksInputController = TextEditingController(); void submitData() { print(nameInputController.text); if (nameInputController.text.isEmpty || marksInputController.text.isEmpty) { return; } widget.addNewUser( nameInputController.text, double.parse(marksInputController.text)); // 提交后主动关闭底部弹窗 Navigator.of(context).pop(); } // 组件销毁时释放控制器,防止内存泄漏 @override void dispose() { nameInputController.dispose(); marksInputController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.end, mainAxisSize: MainAxisSize.min, // 让底部弹窗高度适配内容,不会撑满全屏 children: [ TextField( decoration: const InputDecoration(labelText: "Name"), controller: nameInputController, ), TextField( decoration: const InputDecoration(labelText: "Marks"), controller: marksInputController, keyboardType: TextInputType.number, ), const SizedBox(height: 16,), ElevatedButton( onPressed: submitData, child: const Text('Add User Details'), ), // 避免按钮被键盘遮挡 SizedBox(height: MediaQuery.of(context).viewInsets.bottom,) ], ), ); } }
同步修改说明
- 所有用到
newUsers的地方都要同步改为首字母大写的NewUsers,包括Home.dart里的弹窗返回、body中的组件引用部分。 - 当前添加用户的逻辑里User的id是写死的1,后续列表展示如果用到id作为唯一标识会出现冲突,建议改成自增数值或时间戳作为id。
内容的提问来源于stack exchange,提问作者Himanshu Rahi
相关产品推荐
相关产品推荐

