Flutter中点击TextField后组件重建致键盘闪退的问题求助
解决Flutter表单点击TextField键盘弹出后立即关闭、组件重建的问题
嘿,这个问题我之前开发表单时也踩过坑!核心原因很明确:你把表单的GlobalKey、TextEditingController这些需要持久化状态的变量都放在了build()方法内部——而Flutter的build()会在很多场景下被重新调用(比如键盘弹出、页面布局变化、调用setState()时),每次调用都会重新创建这些变量的新实例,导致TextField失去绑定的控制器,键盘直接关闭,整个表单组件也跟着重置了。
解决步骤
- 把
_formKey、所有TextEditingController移到_UserLoaderState类的成员变量区域,脱离build()方法 - 在
dispose()方法中销毁控制器,避免内存泄漏(规范操作)
修改后的完整代码示例
import 'package:flutter/material.dart'; import '../model/User.dart'; import './FileManager.dart'; import './MyListPage.dart'; class UserLoader extends StatefulWidget { @override _UserLoaderState createState() => new _UserLoaderState(); } class _UserLoaderState extends State<UserLoader> { final userFileName = "user_infos.txt"; User _user; // --- 把状态变量移到类成员区域,确保生命周期内唯一 --- final _formKey = GlobalKey<FormState>(); final _firstNameController = TextEditingController(); final _lastNameController = TextEditingController(); final _emailController = TextEditingController(); final _phoneController = TextEditingController(); @override void dispose() { // --- 销毁控制器,避免内存泄漏 --- _firstNameController.dispose(); _lastNameController.dispose(); _emailController.dispose(); _phoneController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { print("build UserLoader"); // --- 这里不再重新定义状态变量 --- return new Scaffold( appBar: new AppBar( title: new Text("Informations"), actions: <Widget>[ new IconButton( icon: const Icon(Icons.save), onPressed: () { _user = _onFormValidate( _formKey.currentState, _firstNameController.text, _lastNameController.text, _emailController.text, _phoneController.text); }) ], ), body: new Center( child: new SingleChildScrollView( child: new Form( key: _formKey, child: new Column(children: <Widget>[ new ListTile( leading: const Icon(Icons.person), title: new TextFormField( decoration: new InputDecoration( hintText: "Prénom", ), keyboardType: TextInputType.text, controller: _firstNameController, validator: _validateName, ), ), new ListTile( leading: const Icon(Icons.person), title: new TextFormField( decoration: new InputDecoration( hintText: "Nom", ), keyboardType: TextInputType.text, controller: _lastNameController, validator: _validateName, ), ), // 剩下的表单字段直接沿用即可... ]), ), ), ), ); } // 补充你的验证和表单处理方法(示例) String? _validateName(String? value) { if (value == null || value.isEmpty) { return '请输入姓名'; } return null; } User _onFormValidate(FormState? state, String firstName, String lastName, String email, String phone) { state?.save(); return User(firstName: firstName, lastName: lastName, email: email, phone: phone); } }
这样修改后,控制器和表单Key会在State实例的生命周期内保持唯一,不会因为build()重新执行而被重置,键盘弹出后就能正常保持打开状态,用户可以顺利完成表单填写了。
内容的提问来源于stack exchange,提问作者Nadox56




