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

如何从go_router的StatefulShellRoute分支动态生成BottomNavigationBar项

从StatefulShellRoute分支动态生成BottomNavigationBar项

要实现从StatefulShellRoute的分支动态生成底部导航栏项,核心思路是给每个分支路由添加元数据(meta),然后在Scaffold组件中读取这些元数据生成对应的BottomNavigationBarItem。以下是具体实现方案:

1. 给路由分支添加元数据

在定义StatefulShellRoute的branches时,给每个分支的根路由添加meta字段,存储导航栏需要的图标、标签等信息:

final GoRouter _router = GoRouter(
  initialLocation: '/a',
  routes: [
    StatefulShellRoute.indexedStack(
      builder: (context, state, navigationShell) {
        return ScaffoldWithNavBar(navigationShell: navigationShell);
      },
      branches: [
        // 分支A
        StatefulShellBranch(
          routes: [
            GoRoute(
              path: '/a',
              builder: (context, state) => const SectionAScreen(),
              meta: {
                'icon': Icons.home,
                'label': 'Section A',
              },
            ),
          ],
        ),
        // 分支B
        StatefulShellBranch(
          routes: [
            GoRoute(
              path: '/b',
              builder: (context, state) => const SectionBScreen(),
              meta: {
                'icon': Icons.work,
                'label': 'Section B',
              },
            ),
          ],
        ),
        // 分支C
        StatefulShellBranch(
          routes: [
            GoRoute(
              path: '/c',
              builder: (context, state) => const SectionCScreen(),
              meta: {
                'icon': Icons.tab,
                'label': 'Section C',
              },
            ),
          ],
        ),
      ],
    ),
  ],
);

2. 动态生成BottomNavigationBar项

在ScaffoldWithNavBar中,通过navigationShell.route.branches获取所有分支,遍历读取每个分支根路由的元数据,生成导航栏项:

class ScaffoldWithNavBar extends StatelessWidget {
  const ScaffoldWithNavBar({
    required this.navigationShell,
    Key? key,
  }) : super(key: key ?? const ValueKey<String>('ScaffoldWithNavBar'));

  final StatefulNavigationShell navigationShell;

  void _onTap(BuildContext context, int index) {
    // 切换分支并保留页面状态
    navigationShell.goBranch(
      index,
      initialLocation: index == navigationShell.currentIndex,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: navigationShell,
      bottomNavigationBar: BottomNavigationBar(
        // 动态生成导航栏项
        items: navigationShell.route.branches.map((branch) {
          final routeMeta = branch.routes.first.meta;
          final iconData = routeMeta?['icon'] as IconData;
          final label = routeMeta?['label'] as String;
          return BottomNavigationBarItem(
            icon: Icon(iconData),
            label: label,
          );
        }).toList(),
        currentIndex: navigationShell.currentIndex,
        onTap: (index) => _onTap(context, index),
      ),
    );
  }
}

关键说明

  • 元数据存储:利用GoRoute的meta字段存放导航栏配置,这是go_router官方推荐的自定义路由数据方式。
  • 分支遍历逻辑:navigationShell.route.branches返回所有分支路由,每个分支的routes.first即为该分支的根路由,直接读取其meta即可拿到配置信息。
  • 状态保留:使用navigationShell.goBranch切换分支,确保各分支页面的状态被正确保留,符合StatefulShellRoute的设计初衷。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 10:01:30