如何让Bottom Sheet显示在BottomNavBar上方?
系统默认的showModalBottomSheet会以模态方式覆盖整个屏幕(包括BottomNavBar),无法实现你要的效果。你需要通过自定义布局分层来实现,以下是具体实现方案:
核心思路
将BottomNavBar、主内容区域、自定义BottomSheet放在同一个Stack中,让BottomNavBar处于最上层,BottomSheet位于BottomNavBar的上方(屏幕底部到BottomNavBar之间的区域),这样点击logo弹出BottomSheet时,logo始终可见。
代码实现
基础版(带展开/收起动画)
class HomePage extends StatefulWidget { const HomePage({super.key}); @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { bool _isBottomSheetVisible = false; // 根据你的BottomNavBar实际高度调整 final double _bottomNavBarHeight = 60; // 设置BottomSheet的最大展开高度 final double _bottomSheetMaxHeight = 300; void _toggleBottomSheet() { setState(() { _isBottomSheetVisible = !_isBottomSheetVisible; }); } @override Widget build(BuildContext context) { return Scaffold( body: Stack( children: [ // 主内容区域:留出BottomNavBar的高度,避免内容被遮挡 Positioned.fill( bottom: _bottomNavBarHeight, child: const Center(child: Text('主页面内容')), ), // 自定义BottomSheet:位于BottomNavBar上方,带动画展开/收起 AnimatedPositioned( left: 0, right: 0, bottom: _bottomNavBarHeight, height: _isBottomSheetVisible ? _bottomSheetMaxHeight : 0, duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, child: Container( decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( topLeft: Radius.circular(16), topRight: Radius.circular(16), ), boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 10)], ), child: const Center(child: Text('Bottom Sheet内容')), ), ), // BottomNavBar:放在Stack最上层,确保不会被覆盖 Positioned( left: 0, right: 0, bottom: 0, height: _bottomNavBarHeight, child: BottomNavigationBar( items: [ BottomNavigationBarItem( icon: GestureDetector( onTap: _toggleBottomSheet, child: Padding( padding: const EdgeInsets.fromLTRB(0, 4, 0, 8), child: Assets.images.logo.svg(), ), ), label: 'Buy', ), // 其他导航项示例 const BottomNavigationBarItem( icon: Icon(Icons.search), label: 'Search', ), const BottomNavigationBarItem( icon: Icons.person, label: 'Profile', ), ], ), ), ], ), ); } }
进阶版(支持拖拽调整高度)
如果需要像系统BottomSheet一样支持拖拽调整高度,可以用DraggableScrollableSheet替换AnimatedPositioned:
// 替换基础版中的AnimatedPositioned部分 Visibility( visible: _isBottomSheetVisible, child: Positioned( left: 0, right: 0, bottom: _bottomNavBarHeight, height: _bottomSheetMaxHeight, child: DraggableScrollableSheet( initialChildSize: 1, // 初始展开比例(占满设置的height) minChildSize: 0.3, // 最小收起比例 maxChildSize: 1, // 最大展开比例 builder: (context, scrollController) { return Container( decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( topLeft: Radius.circular(16), topRight: Radius.circular(16), ), boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 10)], ), child: ListView( controller: scrollController, children: const [ ListTile(title: Text('选项1')), ListTile(title: Text('选项2')), ListTile(title: Text('选项3')), // 可添加更多列表项 ], ), ); }, ), ), )
为什么原方法无效?
系统showModalBottomSheet是在根导航器层级弹出的模态组件,层级高于所有页面内容(包括Scaffold的bottomNavigationBar),即使设置useRootNavigator: false也无法改变模态框的层级优先级,因此会遮挡BottomNavBar。
内容的提问来源于stack exchange,提问作者kevin
相关产品推荐
相关产品推荐

