You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 18:51:20