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

Flutter开发:如何让Drawer显示在BottomNavigationBar下方?

Flutter Drawer 显示在 BottomNavigationBar 下方实现方案

问题描述

我希望在Flutter应用中同时使用BottomNavigationBar与Drawer组件。当前打开Drawer时,BottomNavigationBar处于Drawer下方(被Drawer覆盖),我想要实现Drawer显示在BottomNavigationBar下方的效果,请问该需求是否可行?

用户原实现代码:

Scaffold(
        key: _scaffoldKey,
        appBar: PreferredSize(
          preferredSize: Size(0.0, 0.0),
          child: Container(),
        ),
        drawer: DrawerWidget(Theme.of(context).brightness, _selectedDrawerIndex, onSelectItem, widget._operator.plannerEnabled, widget._operatorRepository),
        body: _getDrawerItemWidget(_selectedDrawerIndex),
        floatingActionButton: !_showBottoNav() && plannerEnabled
            ? FloatingActionButton(
                elevation: 0.0,
                backgroundColor: Theme.of(context).primaryColor,
                child: Icon(
                  Icons.arrow_forward,
                  color: Colors.white,
                ),
                onPressed: () {
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (context) => ChangeNotifierProvider(
                        create: (context) => PlannerHomeViewModel(context, widget._operator, null, null, null),
                        child: PlannerHomeScreen(),
                      ),
                    ),
                  );
                },
              )
            : null,
        floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
        bottomNavigationBar: !_showBottoNav()
            ? BottomNav(
                onTap: changeSelectedIndex,
                openMenu: manageDrawer,
                showPlanner: plannerEnabled,
                currentIndex: _selectedDrawerIndex ?? 1,
              )
            : null,
      ),

实现方案

这个需求完全可行,默认Scaffold的drawer参数会把Drawer渲染在所有内容之上,要让Drawer显示在BottomNavigationBar下方,需要调整组件层级,具体步骤如下:

  • 移除Scaffold自带的drawer参数,把Drawer作为独立组件放到Scaffold的body层级中
  • 用Stack管理body内的元素,将Drawer放在Stack的底层,页面内容放在上层,这样Drawer会被页面内容覆盖,而BottomNavigationBar因为是Scaffold的bottomNavigationBar参数,层级高于body,自然会显示在Drawer上方
  • 手动维护Drawer的显示/隐藏状态,通过布尔值控制,并添加手势实现点击空白关闭Drawer的效果

修改后的完整代码示例:

bool _isDrawerOpen = false;

@override
Widget build(BuildContext context) {
  return Scaffold(
    key: _scaffoldKey,
    appBar: PreferredSize(
      preferredSize: Size(0.0, 0.0),
      child: Container(),
    ),
    body: Stack(
      children: [
        // Drawer 置于最底层
        if (_isDrawerOpen)
          GestureDetector(
            // 点击遮罩关闭Drawer
            onTap: () => setState(() => _isDrawerOpen = false),
            child: Container(
              color: Colors.black54,
              child: DrawerWidget(
                Theme.of(context).brightness,
                _selectedDrawerIndex,
                (index) {
                  setState(() {
                    _selectedDrawerIndex = index;
                    _isDrawerOpen = false;
                  });
                  onSelectItem(index);
                },
                widget._operator.plannerEnabled,
                widget._operatorRepository,
              ),
            ),
          ),
        // 页面内容置于Drawer上层
        GestureDetector(
          onTap: () {
            if (_isDrawerOpen) setState(() => _isDrawerOpen = false);
          },
          child: _getDrawerItemWidget(_selectedDrawerIndex),
        ),
      ],
    ),
    floatingActionButton: !_showBottoNav() && plannerEnabled
        ? FloatingActionButton(
            elevation: 0.0,
            backgroundColor: Theme.of(context).primaryColor,
            child: Icon(
              Icons.arrow_forward,
              color: Colors.white,
            ),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => ChangeNotifierProvider(
                    create: (context) => PlannerHomeViewModel(context, widget._operator, null, null, null),
                    child: PlannerHomeScreen(),
                  ),
                ),
              );
            },
          )
        : null,
    floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
    bottomNavigationBar: !_showBottoNav()
        ? BottomNav(
            onTap: changeSelectedIndex,
            // 修改openMenu方法,切换Drawer显示状态
            openMenu: () => setState(() => _isDrawerOpen = true),
            showPlanner: plannerEnabled,
            currentIndex: _selectedDrawerIndex ?? 1,
          )
        : null,
  );
}

关键说明

  • 移除了Scaffold原生的drawer,避免其默认的层级覆盖逻辑
  • 通过Stack的子组件顺序控制层级,Drawer在最下层,页面内容在中间层,BottomNavigationBar在最上层
  • 添加了遮罩层和点击关闭手势,模拟原生Drawer的交互体验
  • 手动控制_isDrawerOpen状态来管理Drawer的显示与隐藏

内容的提问来源于stack exchange,提问作者Dawid Długosz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 08:20:35