Flutter切换TextField或改变状态时丢失输入状态的问题求助
问题:TextField切换焦点或关闭键盘时输入内容丢失
我有两个不同的TextField组件,切换焦点到另一个TextField,或者关闭键盘改变状态时,之前输入的内容会全部丢失,就像触发了setState()清除了所有页面数据。我确定是TextEditingController相关的问题,已经创建了两个独立的TextEditingController并传入对应的CustomTextInput组件,还为组件设置了唯一key,但问题依然存在,请问问题出在哪里?
相关代码
FormSection类
class FormSection extends StatelessWidget { final TextEditingController _mailController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); FormSection({ super.key, }); @override Widget build(BuildContext context) { return Column( children: [ CustomTextInput( placeholder: "E - Posta", controller: _mailController, ), const SizedBox(height: 10), CustomTextInput( placeholder: "Şifre", controller: _passwordController, isPassword: true, ), const SizedBox(height: 10), ButtonBar( children: [ LoginPageButtons( buttonText: "Üye Ol", buttonFunction: () {}, ), LoginPageButtons( buttonText: "Giriş Yap", buttonFunction: () { signInWithEmailAndPassword( emailAddress: _mailController.text, password: _passwordController.text); }, ), ], ), ], ); } }
CustomTextInput类
class CustomTextInput extends StatefulWidget { final String placeholder; final TextEditingController controller; final bool? isPassword; CustomTextInput({ Key? key, required this.placeholder, required this.controller, this.isPassword, }) : super(key: key); @override _CustomTextInputState createState() => _CustomTextInputState(); } class _CustomTextInputState extends State<CustomTextInput> { @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(8.0), decoration: BoxDecoration( border: Border.all( color: MainTheme.secondaryColor, // Border color width: 2.0, // Border width ), borderRadius: BorderRadius.circular(10.0), // Border radius ), child: TextFormField( key: widget.key, // Unique key for each TextFormField obscureText: widget.isPassword ?? false, controller: widget.controller, style: MainTheme.themeData.textTheme.displaySmall! .copyWith(color: MainTheme.thirdColor), decoration: InputDecoration( hintStyle: MainTheme.themeData.textTheme.displaySmall! .copyWith(color: MainTheme.thirdColor), hintText: widget.placeholder, // Placeholder text border: InputBorder.none, // Remove the default underline border ), ), ); } }
问题根源与解决办法
问题核心在于FormSection是StatelessWidget,你把TextEditingController直接声明在了StatelessWidget的内部。当Widget树因键盘弹出/收起、焦点切换等场景重建时,StatelessWidget会被重新实例化,导致_mailController和_passwordController被重新初始化,之前存储的输入内容自然丢失。
修复步骤
- 将
FormSection改为StatefulWidget,把TextEditingController移到对应的State类中,利用State的生命周期保存控制器实例 - 在State的
dispose()方法中销毁控制器,避免内存泄漏
修改后的FormSection代码
class FormSection extends StatefulWidget { FormSection({super.key}); @override State<FormSection> createState() => _FormSectionState(); } class _FormSectionState extends State<FormSection> { late final TextEditingController _mailController; late final TextEditingController _passwordController; @override void initState() { super.initState(); _mailController = TextEditingController(); _passwordController = TextEditingController(); } @override void dispose() { _mailController.dispose(); _passwordController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Column( children: [ CustomTextInput( placeholder: "E - Posta", controller: _mailController, ), const SizedBox(height: 10), CustomTextInput( placeholder: "Şifre", controller: _passwordController, isPassword: true, ), const SizedBox(height: 10), ButtonBar( children: [ LoginPageButtons( buttonText: "Üye Ol", buttonFunction: () {}, ), LoginPageButtons( buttonText: "Giriş Yap", buttonFunction: () { signInWithEmailAndPassword( emailAddress: _mailController.text, password: _passwordController.text); }, ), ], ), ], ); } }
另外,CustomTextInput中TextFormField的key: widget.key可以保留,但并非必要,因为控制器已经完成了输入框与数据的关联,不影响功能。
内容的提问来源于stack exchange,提问作者cesebe27
相关产品推荐
相关产品推荐

