Flutter中TextField输入时Dropdown/Radio值重置问题求助
问题:键盘弹出时Dropdown/Radio值重置,TextField不受影响
- 从API获取输入字段数据,选择Dropdown值后,点击TextField弹出键盘时Dropdown值重置;选择Radio按钮时,其他值也会重置。
- 已尝试三种方案无效:1. GlobalKey包裹Dropdown;2. 单独封装ListView.builder为Widget;3. bool变量控制ListView.builder构建。
- 排查发现:键盘弹出时
CarAdOne内的ListView.builder重建,导致Dropdown等控件重新实例化,但TextField值未受影响。
核心问题与修复方案
核心原因
每次ListView.builder重建时,你都在重新生成selectedValueList(覆盖之前的用户选择),而TextField的输入是直接修改已存在的selectedValueList元素,所以没被重置。
修复步骤
把
selectedValueList的初始化移到API数据加载完成后,而非itemBuilder中:
不要在ListView.builder的itemBuilder里每次都重新生成selectedValueList,这会覆盖用户已选择的值。应该在getInputFields成功获取数据后,初始化一次selectedValueList。Dropdown/Radio控件绑定
selectedValueList中的对应值,而非默认值:
比如Dropdown的dropDownValue要从selectedValueList取,而不是固定用data.categoryFieldName;Radio的groupValue也要绑定到selectedValueList的对应值。避免在
itemBuilder中做状态初始化操作:itemBuilder会频繁调用(重建时),任何状态初始化都应该放在initState、didChangeDependencies或者Provider的方法里。
修改后的关键代码
1. 在Provider的getInputFields方法中初始化selectedValueList
// AdsInputField类中的getInputFields方法 Future<void> getInputFields({required String categoryId, required String pageId}) async { // ... 原有API请求逻辑 ... // 数据获取成功后初始化selectedValueList selectedValueList = adsInputFieldList.map((element) { if (element.categoryTypeId == '4') { if (element.attributes.isEmpty) { return AddSummaryModel( name: element.categoryFieldName, nameAr: element.categoryFieldNameArabic, value: [''], field: element.categoryTypeName, ); } else { return AddSummaryModel( name: element.categoryFieldName, nameAr: element.categoryFieldNameArabic, value: List.generate(element.attributes.length, (index) => 'false'), field: element.categoryTypeName, ); } } else { return AddSummaryModel( name: element.categoryFieldName, nameAr: element.categoryFieldNameArabic, value: [''], field: element.categoryTypeName, ); } }).toList(); notifyListeners(); // 通知状态更新 }
2. 修改ListView.builder中的Dropdown和Radio部分
// Dropdown部分(case "2") case "2": var dropdownList = data.attributes .map((e) => e.attributeName) .toSet() .toList(); dropdownList.insert(0, data.categoryFieldName); return Padding( padding: EdgeInsets.symmetric(vertical: 10.h), child: SelectOptionForAd( index: index, dropdownName: data.categoryFieldName, // 绑定selectedValueList中的值,而非默认值 dropDownValue: value.selectedValueList[index].value[0] == '' ? data.categoryFieldName : value.selectedValueList[index].value[0], dropdownlist: dropdownList, // 确保选择后更新selectedValueList onChanged: (newValue) { value.selectedValueList[index].value[0] = newValue; value.notifyListeners(); }, ), ); // Radio部分(case "3") case "3": return Padding( padding: EdgeInsets.symmetric(vertical: 10.h), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ H2semi(text: data.categoryFieldName), for (int radioIndex = 0; radioIndex < data.attributes.length; radioIndex++) RadioListTile( title: H3semi(text: data.attributes[radioIndex].attributeName), value: radioIndex, // 绑定selectedValueList中的值 groupValue: int.tryParse(value.selectedValueList[index].value[0]) ?? 0, onChanged: (newValue) { value.selectedValueList[index].value[0] = newValue.toString(); value.notifyListeners(); }, ), ], ), );
3. 移除itemBuilder中生成selectedValueList的代码
删除ListView.builder的itemBuilder开头的这段代码:
value.selectedValueList = value.adsInputFieldList.map((element) { // ... 原有生成逻辑 ... }).toList();
内容的提问来源于stack exchange,提问作者Numan Ahmad
相关产品推荐
相关产品推荐

