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

如何在Flutter中通过GetX实现同款嵌套导航功能?

问题描述

标签页导航效果

图中展示了一种导航效果:每个标签页都有子页面,返回该标签页时会保留最后访问的页面,再次点击该标签页则回到父页面。此效果在React Native中可通过Stack Navigator轻松实现,请问如何通过GetX路由在Flutter中实现该功能?

我曾在应用中尝试使用IndexedStack,但未达到预期效果,希望通过命名路由实现。


基于GetX的实现方案

核心思路是给每个底部标签页分配独立的路由栈,通过自定义底部导航栏的点击逻辑,实现「切换标签保留栈状态、重复点击回到栈根页面」的效果。

1. 配置多栈路由

在GetX路由配置中,为每个标签页创建嵌套栈,包含该标签的根页面和所有子页面:

List<GetPage> routes = [
  // 首页栈
  GetPage(
    name: '/home',
    page: () => HomeScreen(),
    children: [
      GetPage(name: '/home/detail', page: () => HomeDetailScreen()),
    ],
  ),
  // 发现页栈
  GetPage(
    name: '/discover',
    page: () => DiscoverScreen(),
    children: [
      GetPage(name: '/discover/detail', page: () => DiscoverDetailScreen()),
    ],
  ),
  // 我的页栈
  GetPage(
    name: '/profile',
    page: () => ProfileScreen(),
    children: [
      GetPage(name: '/profile/setting', page: () => SettingScreen()),
    ],
  ),
];

2. 自定义底部导航栏逻辑

用IndexedStack保持未选中标签的页面状态,结合GetNavigator为每个标签绑定独立栈,再通过点击事件处理两种逻辑:

class MainScreen extends StatefulWidget {
  @override
  _MainScreenState createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {
  int _currentIndex = 0;
  // 标记每个标签栈是否已初始化
  final List<bool> _stackInited = [false, false, false];
  // 每个标签对应的根路由
  final List<String> _rootRoutes = ['/home', '/discover', '/profile'];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: IndexedStack(
        index: _currentIndex,
        children: [
          // 每个子项对应一个标签的独立路由栈
          GetNavigator(key: Get.nestedKey(0)),
          GetNavigator(key: Get.nestedKey(1)),
          GetNavigator(key: Get.nestedKey(2)),
        ],
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _currentIndex,
        items: const [
          BottomNavigationBarItem(icon: Icon(Icons.home), label: '首页'),
          BottomNavigationBarItem(icon: Icon(Icons.explore), label: '发现'),
          BottomNavigationBarItem(icon: Icon(Icons.person), label: '我的'),
        ],
        onTap: (index) {
          if (index == _currentIndex) {
            // 重复点击当前标签,回到该栈的根页面
            Get.until((route) => route.settings.name == _rootRoutes[index]);
          } else {
            setState(() => _currentIndex = index);
            // 未初始化的栈,先跳转到根页面
            if (!_stackInited[index]) {
              Get.toNamed(_rootRoutes[index], id: index);
              _stackInited[index] = true;
            }
          }
        },
      ),
    );
  }
}

3. 子页面跳转规则

在标签根页面跳转到子页面时,必须指定对应栈的ID(即标签索引),确保路由进入正确的栈:

// 首页跳转到详情页
Get.toNamed('/home/detail', id: 0);

// 发现页跳转到详情页
Get.toNamed('/discover/detail', id: 1);

关键细节说明

  • Get.nestedKey为每个栈分配独立标识,保证不同标签的路由状态互不干扰
  • IndexedStack避免切换标签时重建页面,保留未选中标签的栈状态
  • Get.until通过判断路由名称,精准回到当前栈的根页面

内容的提问来源于stack exchange,提问作者Hassan Amjad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 06:15:46