BottomSheet中多Checkbox状态更新后界面不勾选问题排查
问题分析与解决方案
错误根源
- 选中状态变量作用域错误:
_checkedState定义在BlocBuilder的builder回调内部,每次builder执行(比如外部setState触发、Bloc状态变化)都会重新初始化这个列表,之前的选中状态会直接丢失。 - 状态刷新范围不匹配:Checkbox的
setState()调用的是外部Widget的状态刷新,但BottomSheet是独立的弹窗路由,外部的setState无法触发BottomSheet内部的UI更新,即使能触发,_checkedState也已经被重置为初始值。
修复方案
将选中状态的管理移到FutureBottomSheetStateful的内部State中,让BottomSheet自行维护选中状态,确保点击Checkbox时的setState能直接刷新弹窗内的UI。
1. 修改FutureBottomSheetStateful组件
class FutureBottomSheetStateful<T> extends StatefulWidget with BaseBottomSheetMixin { const FutureBottomSheetStateful( {required this.future, required this.itemBuilder, this.title = "", this.onItemSelected, this.initialCheckedStates, Key? key}) : super(key: key); final String title; final Future<List<T>> Function() future; final Function(T)? onItemSelected; // 修改itemBuilder,传入选中状态及更新回调 final Widget Function(BuildContext context, T item, int index, bool isChecked, Function(bool) onCheckedChanged) itemBuilder; final List<bool>? initialCheckedStates; @override State<FutureBottomSheetStateful<T>> createState() => _FutureBottomSheetStatefulState<T>(); @override Widget build(BuildContext context) => this; } class _FutureBottomSheetStatefulState<T> extends State<FutureBottomSheetStateful<T>> { late List<bool> _checkedStates; @override void initState() { super.initState(); _checkedStates = widget.initialCheckedStates ?? []; } @override void didUpdateWidget(covariant FutureBottomSheetStateful<T> oldWidget) { super.didUpdateWidget(oldWidget); if (widget.initialCheckedStates != null && widget.initialCheckedStates != oldWidget.initialCheckedStates) { setState(() { _checkedStates = widget.initialCheckedStates!; }); } } @override Widget build(BuildContext context) { var child = FutureBuilder<List<T>>( future: widget.future(), builder: (context, snapshot) { if (snapshot.hasData) { // 确保选中状态列表长度与数据一致 if (_checkedStates.length != snapshot.data!.length) { _checkedStates = List.filled(snapshot.data!.length, false); if (widget.initialCheckedStates != null && widget.initialCheckedStates!.length == snapshot.data!.length) { _checkedStates = List.from(widget.initialCheckedStates!); } } return ListView.builder( physics: const PageScrollPhysics(), shrinkWrap: true, itemCount: snapshot.data!.length, itemBuilder: (context, index) { var item = snapshot.data![index]; return InkWell( onTap: () { if (widget.onItemSelected != null) { widget.onItemSelected!(item); } else { context.pop(item); } }, // 传递选中状态和更新回调给itemBuilder child: widget.itemBuilder(context, item, index, _checkedStates[index], (value) { setState(() { _checkedStates[index] = value; Log.e("chs", _checkedStates[index].toString()); }); }), ); }); } if (snapshot.hasError) { return const PassErrorWidget(); } return const PassLoadingWidget(); }); return BaseBottomSheet(title: widget.title, child: child); } }
2. 修改BlocBuilder中的调用代码
BlocBuilder<PaymentApprovalCubit, SettingsFetchState>( builder: (context, membersState){ if(membersState is SettingsFetchLoaded){ return ClickableFormField( hintText: "Select an option", onPressed: () async { final TeamMembersResponse? result = await FutureBottomSheetStateful<TeamMembersResponse>( future: () => Future.value(membersState.data), itemBuilder: (context, item, index, isChecked, onCheckedChanged) { return Padding( padding: const EdgeInsets.symmetric( vertical: 14, horizontal: 8, ), child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Checkbox( checkColor: AppColors.passBlack, activeColor: AppColors.passBlack.withOpacity(0.1), value: isChecked, onChanged: (value) { onCheckedChanged(value!); }, ), Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "${item.firstName} ${item.lastName}", style: context.textTheme.bodyMedium?.copyWith(fontSize: 14).bold, ), Text( item.email??"", style: const TextStyle( color: AppColors.greySubTitle, fontSize: 12 ), ) ], ) ], ) ); }, ).show(context); setState(() { if (result != null) { // 此处可添加选中后的业务逻辑 } }); }, ); } return const SizedBox.shrink(); }, ),
内容的提问来源于stack exchange,提问作者ibramazin
相关产品推荐
相关产品推荐

