使用Bloc处理悬浮操作按钮点击时底部弹窗重复弹出问题
问题原因
- Cubit 层的
addNewNoteButton方法逻辑缺失:没有先判断当前底部弹窗是否已经处于打开状态(也就是state.isClicked的当前值),只做了表单校验的分支判断,甚至首次点击FAB时如果表单默认校验不通过,都无法正常触发弹窗弹出。 - 视图层没有做重复弹出的拦截:如果状态异常触发多次isClicked为true的回调,会重复调用
showBottomSheet方法。
修复方案
1. 调整Cubit逻辑
优先判断当前弹窗状态,再处理后续校验、存储逻辑:
class HomeCubit extends Cubit<HomeState> { HomeCubit() : super(HomeState.init()); void addNewNoteButton({required bool isClicked}) { // 用户点击FAB,传入true if (isClicked) { // 当前弹窗未打开,先弹出弹窗 if (!state.isClicked) { emit(state.copyWith(isClicked: true)); return; } // 弹窗已打开,校验表单 if (state.inputTextValue.input.isRight()) { // 校验通过,存数据库,关闭弹窗 _database(); emit(state.copyWith(isClicked: false)); return; } // 校验失败,不做状态变更,避免触发弹窗重复弹出 return; } // 传入false,直接更新状态关闭弹窗 emit(state.copyWith(isClicked: false)); } void _database() { // 原有数据库存储逻辑 } }
2. 视图层增加重复弹出拦截
在监听状态弹出底部弹窗时,增加已打开弹窗的判断,避免极端情况重复弹出:
class HomePage extends StatelessWidget { const HomePage(); @override Widget build(BuildContext context) { final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); // 存储当前已打开的底部弹窗控制器 PersistentBottomSheetController? bottomSheetController; return BlocListener<HomeCubit, HomeState>( listener: (context, state) { if (state.isClicked) { // 只有没有已打开的弹窗时才执行弹出操作 if (bottomSheetController == null) { bottomSheetController = _scaffoldKey.currentState! .showBottomSheet( (context) => const AddNewNoteBottomSheet(), ); bottomSheetController?.closed.then((value) { bottomSheetController = null; context.read<HomeCubit>().addNewNoteButton(isClicked: false); }); } } else { // 状态变为关闭时,主动关闭已有的弹窗 bottomSheetController?.close(); bottomSheetController = null; } }, child: DefaultTabController( length: 3, child: Scaffold( key: _scaffoldKey, floatingActionButton: InkWell( onTap: () { context.read<HomeCubit>().addNewNoteButton(isClicked: true); }, child: Container( child: Icon( Icons.add, color: const Color(whiteColor), size: 9.h, ), ), ), // 原有Scaffold其余逻辑 ), ), ); } }
内容的提问来源于stack exchange,提问作者Mariam Albarghouti
相关产品推荐
相关产品推荐

