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

Flutter中如何在BottomNavigationBar同一图标下跳转页面

问题

已实现带有3个图标的BottomNavigationBar,每个图标对应一个页面。但希望从第一个图标对应的页面(索引0)跳转到其他页面时,保持该图标的选中状态,且BottomNavigationBar不消失。目前使用Navigator.push跳转时,底部导航栏会消失,因为打开了全新页面。

解决方案

核心思路是让每个Tab页面拥有独立的导航栈,这样Tab内部的页面跳转不会影响外层的BottomNavigationBar。具体实现方式是给每个Tab对应的页面嵌套Navigator组件,而非直接使用全局Navigator。

修改步骤

  1. 为每个Tab分配独立的GlobalKey<NavigatorState>,用于管理Tab内的导航状态
  2. 使用Stack + Offstage组合控制Tab页面的显示/隐藏,保留未选中Tab的状态
  3. 让每个Tab页面在自身的Navigator栈内完成跳转

完整代码示例

修改后的MainPage代码

class MainPage extends StatefulWidget {
  const MainPage({Key? key}) : super(key: key);

  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  int currentIndex = 0;
  // 为每个Tab维护独立的Navigator状态Key
  final List<GlobalKey<NavigatorState>> _navigatorKeys = [
    GlobalKey<NavigatorState>(),
    GlobalKey<NavigatorState>(),
    GlobalKey<NavigatorState>(),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      bottomNavigationBar: BottomNavigationBar(
        backgroundColor: const Color(0xfffbfbfb),
        currentIndex: currentIndex,
        selectedItemColor: const Color(0xff5bc0de),
        unselectedItemColor: Colors.black,
        type: BottomNavigationBarType.shifting,
        onTap: (index) {
          // 点击当前选中Tab时,返回该Tab的根页面
          if (index == currentIndex) {
            _navigatorKeys[index].currentState?.popUntil((route) => route.isFirst);
          } else {
            setState(() {
              currentIndex = index;
            });
          }
        },
        items: const [
          BottomNavigationBarItem(
            icon: Image.asset("assets/home.png"),
            label: "Home",
          ),
          BottomNavigationBarItem(
            icon: Image.asset("assets/meeting.png"),
            label: "Schedule",
          ),
          BottomNavigationBarItem(
            icon: Image.asset("assets/notification.png"),
            label: "Alert",
          ),
        ],
      ),
      body: Stack(
        children: List.generate(3, (index) {
          return Offstage(
            offstage: currentIndex != index,
            child: Navigator(
              key: _navigatorKeys[index],
              onGenerateRoute: (settings) {
                return MaterialPageRoute(
                  builder: (context) {
                    // 根据索引返回对应Tab的初始页面
                    switch (index) {
                      case 0:
                        return const Home();
                      case 1:
                        return const Home(); // 替换为你的Schedule页面
                      case 2:
                        return const Home(); // 替换为你的Alert页面
                      default:
                        return const Home();
                    }
                  },
                );
              },
            ),
          );
        }),
      ),
    );
  }
}

修改后的Home页面代码

class Home extends StatefulWidget {
  const Home({Key? key}) : super(key: key);

  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        width: 800,
        height: 800,
        color: Colors.blue,
        child: Center(
          child: InkWell(
            onTap: () {
              // 在当前Tab的Navigator栈内跳转,不影响外层导航栏
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => const Second()),
              );
            },
            child: const Text("helllo"),
          ),
        ),
      ),
    );
  }
}

// 示例跳转目标页面
class Second extends StatelessWidget {
  const Second({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Second Page")),
      body: const Center(child: Text("This is Second Page")),
    );
  }
}

原理说明

  • 独立Navigator栈:每个Tab的页面跳转都在自身Navigator中完成,外层Scaffold的BottomNavigationBar始终保持可见
  • GlobalKey控制:通过GlobalKey可以精准控制每个Tab内的导航状态,比如点击当前Tab时返回根页面
  • Stack + Offstage:未选中的Tab会被隐藏但保留状态,切换Tab时不会重新初始化页面,提升体验

内容的提问来源于stack exchange,提问作者Ahmed Elsayed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 23:54:24