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

Flutter中如何移除底部导航栏白色背景并实现悬浮效果

Flutter 底部导航栏悬浮实现方案

问题说明

开发底部导航栏时,需要让导航栏悬浮在标签页内容上方,首页内容可在导航栏下方滚动(琥珀色区域为内容区)。但使用body: screens[_currentIndex]时,底部导航栏带有与Scaffold一致的白色背景,无法呈现悬浮效果。

解决思路

默认Scaffold的bottomNavigationBar会占据底部固定空间,且背景继承自Scaffold,导致内容无法滚动到导航栏下方。要实现悬浮效果,需将导航栏通过Stack+Positioned叠加在内容之上,同时给内容添加底部内边距避免遮挡。

修改后的完整代码

class MainMenu extends StatefulWidget {
  const MainMenu({super.key});
  static const String id = "landingpage";

  @override
  State<MainMenu> createState() => _MainMenuState();
}

class _MainMenuState extends State<MainMenu> {
  GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();

  int _currentIndex = 0;

  // 定义标签页页面
  final List<Widget> screens = [
    FavoritePage(),
    HomePage(),
    ListingsPage(),
    ProfilePage(),
  ];
  bool drawerCanOpen = true;
  final kDrawerItemStyle = TextStyle(
    fontSize: 16,
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.amber,
      key: scaffoldKey,
      body: Stack(
        children: [
          NestedScrollView(
            headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
              return <Widget>[
                _currentIndex <= 0
                    ? SliverAppBar(
                        foregroundColor: Color.fromARGB(255, 12, 3, 3),
                        title: Row(children: []),
                        leading: Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: CircleAvatar(
                            backgroundColor: Color.fromARGB(255, 255, 255, 255),
                            radius: 20,
                            child: IconButton(
                              icon: FaIcon(FontAwesomeIcons.bars),
                              onPressed: () {
                                if (drawerCanOpen) {
                                  scaffoldKey.currentState?.openDrawer();
                                } else {
                                  setState(() {
                                    drawerCanOpen = true;
                                  });
                                }
                              },
                              color: Colors.black87,
                            ),
                          ),
                        ),
                        actions: [
                          Padding(
                            padding: const EdgeInsets.all(8.0),
                            child: Container(
                              decoration: BoxDecoration(
                                color: Color.fromARGB(255, 18, 255, 0),
                                borderRadius: BorderRadius.circular(20),
                                boxShadow: [
                                  BoxShadow(
                                    color: Colors.black26,
                                    blurRadius: 5.0,
                                    spreadRadius: 0.5,
                                    offset: Offset(
                                      0.7,
                                      0.7,
                                    ),
                                  ),
                                ],
                              ),
                              child: Badge(
                                backgroundColor: Colors.red,
                                padding: const EdgeInsets.all(7),
                                textStyle: const TextStyle(fontSize: 10.0),
                                largeSize: 20.0,
                                label: const Text('1'),
                                child: CircleAvatar(
                                  backgroundColor: Colors.white,
                                  radius: 20,
                                  child: IconButton(
                                    icon: FaIcon(FontAwesomeIcons.bagShopping),
                                    onPressed: () {
                                      Get.to(() => const CartPage(),
                                          duration:
                                              const Duration(milliseconds: 200),
                                          transition: Transition.rightToLeft);
                                    },
                                    color: Colors.black87,
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ],
                        expandedHeight: 50,
                        scrolledUnderElevation: 2,
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(5.0)),
                        floating: false,
                        pinned: true,
                        elevation: innerBoxIsScrolled ? 4 : 0,
                        flexibleSpace: FlexibleSpaceBar(
                          centerTitle: true,
                          background: Container(
                            color: Colors.amber,
                          ),
                        ),
                      )
                    : SliverToBoxAdapter(
                        child: SizedBox.shrink(),
                      ),
              ];
            },
            // 添加底部内边距,避免内容被导航栏遮挡
            body: Padding(
              padding: EdgeInsets.only(bottom: 80), // 数值根据导航栏高度+底部padding调整
              child: screens[_currentIndex],
            ),
          ),
          // 悬浮的底部导航栏
          Positioned(
            left: 50,
            right: 50,
            bottom: 30,
            child: ClipRRect(
              borderRadius: BorderRadius.circular(30.0),
              child: BottomNavigationBar(
                backgroundColor: Colors.white,
                type: BottomNavigationBarType.fixed,
                currentIndex: _currentIndex,
                onTap: (index) {
                  setState(() {
                    _currentIndex = index;
                  });
                },
                elevation: 4.0, // 加阴影增强悬浮感
                showSelectedLabels: false,
                showUnselectedLabels: false,
                items: [
                  BottomNavigationBarItem(
                    icon: Icon(Icons.home),
                    label: '',
                  ),
                  BottomNavigationBarItem(
                    icon: Icon(Icons.search),
                    label: '',
                  ),
                  BottomNavigationBarItem(
                    icon: Icon(Icons.favorite),
                    label: '',
                  ),
                  BottomNavigationBarItem(
                    icon: Icon(Icons.person),
                    label: '',
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

关键修改点

  • 移除Scaffold的bottomNavigationBar参数,改用Stack布局将导航栏叠加在内容之上
  • 通过Positioned精准定位导航栏的左右、底部边距
  • 给NestedScrollView的body添加底部内边距,确保内容不会被悬浮导航栏遮挡
  • 给导航栏添加elevation属性,通过阴影增强悬浮视觉效果

内容的提问来源于stack exchange,提问作者Leo.roxy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 20:12:04