Flutter Cubit中更新TextFormField异常:点击或API取数后光标跳转
问题描述
我通过Cubit实现表单验证,页面包含两个输入组件:可编辑的Address输入框,以及禁用状态的Remarks输入框。需求是点击Remarks输入框时,将Address输入框的值设置为"Hello"。
当给Address的TextField添加以下代码后,点击Remarks确实能成功赋值,但修改Address内容时出现异常:每次删除或输入字符,光标都会跳回输入框起始位置。
controller: TextEditingController( text: state.formFields['address']?.value, ),
问题原因
每次Cubit状态更新触发BlocBuilder重建时,都会创建一个新的TextEditingController实例。新的控制器会重置光标位置到文本开头,导致输入体验异常。
解决方案
将_AddressInput从无状态组件改为有状态组件,在组件内部持有唯一的TextEditingController实例,通过监听Cubit状态变化来更新控制器文本,而非每次重建都新建控制器。
修改后的_AddressInput代码
class _AddressInput extends StatefulWidget { @override State<_AddressInput> createState() => _AddressInputState(); } class _AddressInputState extends State<_AddressInput> { late TextEditingController _controller; @override void initState() { super.initState(); _controller = TextEditingController(); // 初始化获取Address的初始值 final cubit = context.read<GenericFormFieldCubit>(); final initialValue = (cubit.state.formFields['address'] as UserNameInputField).value; _controller.text = initialValue; } @override void dispose() { _controller.dispose(); // 销毁控制器避免内存泄漏 super.dispose(); } @override Widget build(BuildContext context) { return BlocListener<GenericFormFieldCubit, GenericFormFieldState>( listenWhen: (previous, current) => previous.formFields['address'] != current.formFields['address'], listener: (context, state) { final latestValue = (state.formFields['address'] as UserNameInputField).value; // 仅当值不同时更新,避免不必要的光标跳动 if (_controller.text != latestValue) { _controller.text = latestValue; } }, child: TextField( controller: _controller, key: const Key('personalInfoForm_addressInput_textField'), onChanged: (value) { final name = UserNameInputField.custom( value, errorMessage: '请输入有效地址', requiredMessage: '此字段为必填项', minValue: '5', maxValue: '20', ); context.read<GenericFormFieldCubit>().updateField('address', name); }, decoration: InputDecoration( labelText: '地址', errorText: (context.read<GenericFormFieldCubit>().state.formFields['address'] as UserNameInputField).invalid ? (context.read<GenericFormFieldCubit>().state.formFields['address'] as UserNameInputField).getErrorMessage : null, ), ), ); } }
额外优化:简化RemarksInput代码
由于Remarks输入框是禁用且只读状态,无需监听自身状态变化,可以移除多余的BlocBuilder:
class _RemarksInput extends StatelessWidget { @override Widget build(BuildContext context) { return GestureDetector( onTap: () { context.read<GenericFormFieldCubit>().updateField('address', UserNameInputField.custom("Hello")); }, child: TextField( enabled: false, readOnly: true, key: const Key("personalInfoForm_remarksInput_textField"), decoration: const InputDecoration( labelText: '备注', ), ), ); } }
内容的提问来源于stack exchange,提问作者Rabindra Acharya
相关产品推荐
相关产品推荐

