Flutter ListView内按钮调用setState后isSelected状态不更新如何解决?
问题根因
- 你在循环中定义的
isSelectedValue是局部临时变量,每次组件执行build时都会被重置为false,即便你在setState中修改了这个局部变量,下次渲染时也会被覆盖,不会生效。 - Dart采用值传递的逻辑,你传入
getReminderTypesButton的reminderVariable是newReminder.type/newReminder.repeatFrequency的副本,你在回调中修改reminderVariable并不会真正改变外层newReminder对象的属性,你看到的打印结果只是局部变量的值,实际状态并未更新。
解决方法
你不需要额外存储选中状态,直接通过newReminder的当前属性值判断按钮是否选中即可,同时修改传参逻辑直接更新newReminder的对应属性:
- 改造
getReminderTypesButton方法,接收选中回调和当前选中值作为参数,把方法放到State类中,不要定义在build方法内:
List<Widget> getReminderTypesButton( List selectionOptions, Function(String) onSelect, String currentSelectedValue ) { List<Widget> selectionOptionsWidgets = []; for (String selection in selectionOptions) { // 直接通过当前选中值判断按钮状态 bool isSelectedValue = selection == currentSelectedValue; selectionOptionsWidgets.add( FullWidthButton( text: selection, isSelected: isSelectedValue, onPress: () { setState(() { onSelect(selection); }); }, ), ); } return selectionOptionsWidgets; }
- 把
widgetListUnwrap方法移到build外部,避免每次渲染重复声明:
List<Widget> widgetListUnwrap(List<List<Widget>> inputList) { List<Widget> widgetsUnwrapped = []; for (var mainList in inputList) { widgetsUnwrapped.addAll(mainList); } return widgetsUnwrapped; }
- 修改build中的调用逻辑:
@override Widget build(BuildContext context) { List<List<Widget>> newList = [ getReminderTypesButton( reminderTypesList, (val) => newReminder.type = val, newReminder.type ), getReminderTypesButton( repeatFrequencyTypesList, (val) => newReminder.repeatFrequency = val, newReminder.repeatFrequency ) ]; // 其余原有布局代码保持不变即可 }
补充说明
- 你完全可以在ListView中传入自定义按钮并正常更新状态,不需要更换实现方案。
- 如果初始状态下所有按钮都未选中,检查
Reminder类的type和repeatFrequency的初始值是否在选项列表中,可默认赋值为列表第一个选项即可。
内容的提问来源于stack exchange,提问作者davenz
相关产品推荐
相关产品推荐

