Flutter中SnackBar显示在Expandable Bottom Bar上方问题求助
解决Expandable Bottom Bar与SnackBar层级冲突问题
我使用expandable_bottom_bar实现了可展开的底部导航栏,但显示SnackBar时,它会渲染在BottomExpandableAppBar上方,遮挡了底部栏内容。页面是基础的Scaffold结构,核心代码如下:
class HomePage extends StatelessWidget { const HomePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: const Center( child: Text("HOME SCREEN"), ), floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, floatingActionButton: GestureDetector( onVerticalDragUpdate: DefaultBottomBarController.of(context) .onDrag, //Caso queiram voltar com a funcionalidade de arrastar onVerticalDragEnd: DefaultBottomBarController.of(context).onDragEnd, child: FloatingActionButton( onPressed: () => DefaultBottomBarController.of(context).swap(), elevation: 4, foregroundColor: Colors.white, child: AnimatedBuilder( animation: DefaultBottomBarController.of(context).state, builder: (context, child) => Container( child: (DefaultBottomBarController.of(context).isOpen) ? menuEasyLogoButtom : wavesEasyLogoButtom), ), ), ), bottomNavigationBar: BottomExpandableAppBar( expandedHeight: 340, bottomOffset: 0, expandedDecoration: BoxDecoration( borderRadius: BorderRadius.circular(8), color: ThemeColors.backGroundColor, boxShadow: <BoxShadow>[ BoxShadow( color: Colors.black.withOpacity(0.2), offset: const Offset(0, 5), spreadRadius: 2, blurRadius: 9, ) ]), expandedBody: const ExpandedDashBoardIcons(), shape: const AutomaticNotchedShape( RoundedRectangleBorder(), StadiumBorder(side: BorderSide())), bottomAppBarBody: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Padding( padding: const EdgeInsets.only(left: 64.0), child: InkWell( onTap: () { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text("This is not supossed to be shown here...")), ); }, child: const Icon( Icons.monetization_on_outlined, size: 33.33, color: ThemeColors.primaryFontColor, ), ), ), Padding( padding: const EdgeInsets.only(right: 64.0), child: InkWell( onTap: () {}, child: const Icon( Icons.sailing_rounded, size: 33.33, color: ThemeColors.primaryFontColor, )), ), ], ), ), ); } }
解决方法
方法1:改用悬浮式SnackBar
最简单的方式是修改SnackBar的behavior为SnackBarBehavior.floating,这样SnackBar会悬浮在页面内容上方,自动避开底部栏:
ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text("This should display above the bottom bar now!"), behavior: SnackBarBehavior.floating, ), );
方法2:调整组件嵌套结构
如果需要保持SnackBar的默认固定样式,可将BottomExpandableAppBar从bottomNavigationBar参数移到Scaffold的body内的Stack中,让Scaffold的SnackBar默认渲染在最上层:
class HomePage extends StatelessWidget { const HomePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( resizeToAvoidBottomInset: true, body: Stack( children: [ // 页面主内容 const Center(child: Text("HOME SCREEN")), // 将底部栏放在Stack底部 Positioned( left: 0, right: 0, bottom: 0, child: BottomExpandableAppBar( expandedHeight: 340, bottomOffset: 0, expandedDecoration: BoxDecoration( borderRadius: BorderRadius.circular(8), color: ThemeColors.backGroundColor, boxShadow: <BoxShadow>[ BoxShadow( color: Colors.black.withOpacity(0.2), offset: const Offset(0, 5), spreadRadius: 2, blurRadius: 9, ) ]), expandedBody: const ExpandedDashBoardIcons(), shape: const AutomaticNotchedShape( RoundedRectangleBorder(), StadiumBorder(side: BorderSide())), bottomAppBarBody: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Padding( padding: const EdgeInsets.only(left: 64.0), child: InkWell( onTap: () { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text("This is now displayed correctly!")), ); }, child: const Icon( Icons.monetization_on_outlined, size: 33.33, color: ThemeColors.primaryFontColor, ), ), ), Padding( padding: const EdgeInsets.only(right: 64.0), child: InkWell( onTap: () {}, child: const Icon( Icons.sailing_rounded, size: 33.33, color: ThemeColors.primaryFontColor, )), ), ], ), ), ), ], ), floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, floatingActionButton: GestureDetector( onVerticalDragUpdate: DefaultBottomBarController.of(context).onDrag, onVerticalDragEnd: DefaultBottomBarController.of(context).onDragEnd, child: FloatingActionButton( onPressed: () => DefaultBottomBarController.of(context).swap(), elevation: 4, foregroundColor: Colors.white, child: AnimatedBuilder( animation: DefaultBottomBarController.of(context).state, builder: (context, child) => Container( child: (DefaultBottomBarController.of(context).isOpen) ? menuEasyLogoButtom : wavesEasyLogoButtom), ), ), ), ); } }
说明
- 方法1无需修改页面结构,适合快速解决问题;
- 方法2通过调整组件层级,让SnackBar保持默认样式的同时,始终显示在底部栏上方,更贴合原生体验。
内容的提问来源于stack exchange,提问作者rafaelpadu
相关产品推荐
相关产品推荐

