Flutter:BlocSelector重建后TextFormField丢失焦点问题求助
解决Flutter Bloc动态表单输入框失去焦点问题
问题根源
你当前使用UniqueKey()作为TextFormField的key,每次Bloc状态更新触发BlocSelector重建时,所有输入框都会生成新的UniqueKey。Flutter会将这些视为全新的组件,销毁旧输入框并重建,直接导致输入焦点丢失。
解决方案
核心是给每个输入框分配稳定且唯一的Key,避免重建时组件被误判为新元素。最优方案是让每个输入项携带唯一标识,而非仅存储字符串:
- 定义带唯一ID的输入项实体
class AnswerItem { final String id; String value; AnswerItem({required this.id, required this.value}); }
- 调整Bloc状态与事件处理
将原状态中的List<String> answerList改为List<AnswerItem> answerList,同步更新事件逻辑:
- 添加新项时生成唯一ID(可使用
DateTime.now().microsecondsSinceEpoch.toString()或Uuid包) - 修改、删除操作基于索引或ID定位项(推荐用ID更稳定)
- 更新UI层代码
用ValueKey(item.id)作为TextFormField的key,确保组件重建时key保持稳定:
class AddQuestionScreenBody extends StatelessWidget { AddQuestionScreenBody({super.key}); final GlobalKey _formKey = GlobalKey<FormState>(); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.only(right: 15.0, left: 15.0), child: Form( key: _formKey, child: Column( children: [ BlocSelector<AddQuestionBloc, AddQuestionState, List<AnswerItem>>( selector: (state) => state.answerList, builder: (context, answerList) { return Column( children: [ for (int i = 0; i < answerList.length; i++) Padding( padding: const EdgeInsets.only(bottom: 15.0), child: TextFormField( // 使用基于唯一ID的稳定Key key: ValueKey(answerList[i].id), initialValue: answerList[i].value, validator: (value) { if (value == null || value.isEmpty) { return "Answer is required"; } return null; }, onChanged: (value) { context.read<AddQuestionBloc>().add( OnChangeAnswerElement( index: i, value: value, ), ); }, decoration: InputDecoration( label: Text('Answer ${i + 1}'), suffixIconColor: Colors.redAccent, suffixIcon: IconButton( onPressed: () { context.read<AddQuestionBloc>().add( OnRemoveAnswerElement(i), ); }, icon: const Icon(Icons.remove), ), ), ), ), ElevatedButton( onPressed: () { context.read<AddQuestionBloc>().add( OnAddAnswerElement(), ); }, child: const Icon(Icons.add), ), ], ); }, ), ], ), ), ); } }
临时替代方案(不推荐)
如果暂时不想修改状态结构,可尝试用ValueKey('answer_${answerList[i]}_$i')作为key,但当存在重复输入值或删除中间项时,仍可能出现焦点问题,仅适用于简单场景。
内容的提问来源于stack exchange,提问作者Justin Timbersaw
相关产品推荐
相关产品推荐

