Flutter使用ListTile时勾选Checkbox如何同步TextField值到对应输入框
问题根因
你所有列表条目共用了全局的同一个charges和time文本编辑控制器,控制器内容变更会同步到所有绑定它的输入框,所以修改一个就会导致所有条目同步变化。
解决方案
给每个列表条目单独分配独立的文本编辑控制器,通过Map以book的id为key存储对应条目的控制器,修改时仅操作当前选中条目对应的控制器即可。
步骤1:替换全局控制器定义
删除原来全局的charges、time控制器,新增Map存储每个条目的独立控制器:
TextEditingController chargesMax = TextEditingController(); List _selectedCities = []; // 以book.id为key,存储对应条目的控制器 Map<int, TextEditingController> chargesControllerMap = {}; Map<int, TextEditingController> timeControllerMap = {};
步骤2:修改选中逻辑,仅给当前条目控制器赋值
void _onCitySelected(bool selected, cityId) { if (selected == true) { setState(() { // 若当前条目无控制器则先初始化 if (!chargesControllerMap.containsKey(cityId)) { chargesControllerMap[cityId] = TextEditingController(); timeControllerMap[cityId] = TextEditingController(); } // 仅给当前选中条目的charges输入框赋值 chargesControllerMap[cityId]!.text = chargesMax.text; _selectedCities.add(cityId); }); } else { setState(() { _selectedCities.remove(cityId); // 可选:取消选中时释放对应控制器节约内存 chargesControllerMap[cityId]?.dispose(); timeControllerMap[cityId]?.dispose(); chargesControllerMap.remove(cityId); timeControllerMap.remove(cityId); }); } }
步骤3:修改列表条目组件,绑定对应独立控制器
修改buildCitesList方法中输入框绑定的控制器,不再使用全局控制器,改为读取当前book.id对应的独立控制器:
Widget buildCitesList(Book book) => ListTile( leading: checkboxCustom(context, _selectedCities.contains(book.id), (bool? selected) { if (selected != null) { setState(() { _onCitySelected(selected, book.id); }); } }), title: Text(book.title, style: GoogleFonts.montserrat()), subtitle: Padding( padding: const EdgeInsets.only(top: 10), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 确保当前条目控制器已初始化 if (!chargesControllerMap.containsKey(book.id)) { chargesControllerMap[book.id] = TextEditingController(); } if (!timeControllerMap.containsKey(book.id)) { timeControllerMap[book.id] = TextEditingController(); }, //charges输入框绑定当前条目对应控制器 textformfieldCustomwithouticon1( context, TextInputType.number, MediaQuery.of(context).size.width * 0.3, chargesControllerMap[book.id]!, (String value) { setState(() { chargesControllerMap[book.id]!.text = value; chargesControllerMap[book.id]!.selection = TextSelection.fromPosition( TextPosition(offset: chargesControllerMap[book.id]!.text.length)); }); }, (value) { if (value == null || value.isEmpty) { return '请输入内容'; } return null; }, '费用', '费用', 10.0), SizedBox( width: 10, ), // time输入框绑定当前条目对应控制器 textformfieldCustomwithouticon1( context, TextInputType.number, MediaQuery.of(context).size.width * 0.3, timeControllerMap[book.id]!, (String value) { setState(() { timeControllerMap[book.id]!.text = value; timeControllerMap[book.id]!.selection = TextSelection.fromPosition( TextPosition(offset: timeControllerMap[book.id]!.text.length)); }); }, (value) { if (value == null || value.isEmpty) { return '请输入内容'; } return null; }, '时间', '时间', 10.0), ], ), ), );
步骤4:页面销毁时释放所有控制器
重写页面的dispose方法,避免内存泄漏:
@override void dispose() { chargesMax.dispose(); // 释放所有条目控制器 for (var controller in chargesControllerMap.values) { controller.dispose(); } for (var controller in timeControllerMap.values) { controller.dispose(); } super.dispose(); }
内容的提问来源于stack exchange,提问作者TimeToCode
相关产品推荐
相关产品推荐

