Flutter:如何让showModalBottomSheet原生显示在bottomNavigationBar上方
需求
不使用Stack或自定义组件,通过Flutter原生API实现showModalBottomSheet触发后显示在bottomNavigationBar上方。
当前代码
body: Navigator( onGenerateRoute: (settings) { return MaterialPageRoute( builder: (context) { return ListView( children: [ TextButton( onPressed: () { showModalBottomSheet( // 从Navigator内部触发 useRootNavigator: false, context: context, builder: (_) => const SizedBox( height: 200, child: Text( 'Modal bottom sheet', style: TextStyle(fontSize: 30), ), ), ); }, child: CustomText().darkGrey( txt: 'Add to wishlist', size: 17, ), ), const DetailProductStoreName(), ], ); }, ); }, ), bottomNavigationBar: AddToCartBottomNav(), // 需要从这里触发弹窗
当前问题
- 从body内的Navigator触发弹窗时,弹窗能正常显示在bottomNavigationBar上方
- 从bottomNavigationBar触发时,弹窗无法达到上述效果
期望效果
从bottomNavigationBar触发showModalBottomSheet时,弹窗显示在「Add to Cart」按钮上方。
解决方案
核心思路
问题根源在于bottomNavigationBar使用的是根Navigator的context,弹窗默认挂载在根Navigator的Overlay中,层级低于bottomNavigationBar;而body内的嵌套Navigator的context对应的Overlay层级在bottomNavigationBar之上,所以从内部触发时弹窗能覆盖它。
只需让bottomNavigationBar触发弹窗时,使用嵌套Navigator的context,并保持useRootNavigator: false即可。
修改步骤及代码
- 给嵌套Navigator添加GlobalKey,用于获取它的context
final GlobalKey<NavigatorState> _nestedNavigatorKey = GlobalKey<NavigatorState>();
- 更新body内的Navigator,绑定这个Key
body: Navigator( key: _nestedNavigatorKey, // 绑定GlobalKey onGenerateRoute: (settings) { return MaterialPageRoute( builder: (context) { return ListView( children: [ TextButton( onPressed: () { showModalBottomSheet( useRootNavigator: false, context: context, builder: (_) => const SizedBox( height: 200, child: Text( 'Modal bottom sheet', style: TextStyle(fontSize: 30), ), ), ); }, child: CustomText().darkGrey( txt: 'Add to wishlist', size: 17, ), ), const DetailProductStoreName(), ], ); }, ); }, ),
- 修改bottomNavigationBar的触发逻辑,使用嵌套Navigator的context
假设AddToCartBottomNav支持传入点击回调:
bottomNavigationBar: AddToCartBottomNav( onCartPressed: () { if (_nestedNavigatorKey.currentContext != null) { showModalBottomSheet( useRootNavigator: false, context: _nestedNavigatorKey.currentContext!, builder: (_) => const SizedBox( height: 200, child: Text( 'Modal bottom sheet', style: TextStyle(fontSize: 30), ), ), ); } }, ),
原理说明
- 嵌套Navigator的Overlay层级在bottomNavigationBar之上,使用它的context调用
showModalBottomSheet并设置useRootNavigator: false,弹窗会挂载到这个Overlay中,自然就显示在bottomNavigationBar上方 - 全程使用Flutter原生API,无需额外的Stack或自定义组件
内容的提问来源于stack exchange,提问作者rooxane.mac
相关产品推荐
相关产品推荐

