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

Flutter使用AutoRoute时结合顶部TabBar与底部导航更新Scaffold Body

Flutter + AutoRoute 双Tab区域(顶部+底部)内容动态切换实现方案

1. 路由层配置(AutoRoute)

先做嵌套路由配置,把全局底部导航所在的页面作为父路由,底部导航对应的各个标签页作为它的子路由:

@MaterialAutoRouter(
  routes: [
    // 带全局底部导航的父路由
    AutoRoute(
      path: '/root',
      page: RootScaffoldPage, // 仅承载底部导航和子路由占位
      children: [
        AutoRoute(path: 'home', page: HomePage), // 首页,带顶部TabBar
        AutoRoute(path: 'category', page: CategoryPage), // 底部导航其他页
        AutoRoute(path: 'mine', page: MinePage), // 底部导航其他页
      ],
    ),
    // 不需要底部导航的页面放在外层即可
    AutoRoute(path: '/detail', page: DetailPage),
  ],
)
class AppRouter extends _$AppRouter {}

所有子路由都会在RootScaffoldPage的body区域渲染,因此底部导航可以全局生效,不需要每个页面重复配置。

2. 父级底部导航页面实现

class RootScaffoldPage extends StatefulWidget {
  const RootScaffoldPage({super.key});

  @override
  State<RootScaffoldPage> createState() => _RootScaffoldPageState();
}

class _RootScaffoldPageState extends State<RootScaffoldPage> {
  final _bottomNavItems = const [
    BottomNavigationBarItem(icon: Icon(Icons.home), label: '首页'),
    BottomNavigationBarItem(icon: Icon(Icons.category), label: '分类'),
    BottomNavigationBarItem(icon: Icon(Icons.person), label: '我的'),
  ];

  @override
  Widget build(BuildContext context) {
    return AutoTabsRouter(
      routes: const [
        HomeRoute(),
        CategoryRoute(),
        MineRoute(),
      ],
      builder: (context, child, animation) {
        final tabsRouter = AutoTabsRouter.of(context);
        return Scaffold(
          // 全局底部导航仅在这里配置一次
          bottomNavigationBar: BottomNavigationBar(
            currentIndex: tabsRouter.activeIndex,
            onTap: tabsRouter.setActiveIndex,
            items: _bottomNavItems,
          ),
          body: child,
        );
      },
    );
  }
}

切换底部导航标签时,AutoTabsRouter会自动替换body区域的子路由页面,除了HomeRoute对应的首页外,其他子路由页面本身不配置顶部TabBar,自然不会显示该组件。

3. 首页顶部TabBar实现

首页单独配置带TabBar的AppBar,切换顶部标签仅更新当前首页的body内容,不触发全局路由切换:

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
  late TabController _tabController;
  final _topTabs = const [
    Tab(text: '推荐'),
    Tab(text: '关注'),
    Tab(text: '热点'),
  ];
  // 顶部Tab对应的页面列表
  final _topTabPages = const [
    RecommendPage(),
    FollowPage(),
    HotPage(),
  ];

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: _topTabs.length, vsync: this);
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('首页'),
        // 顶部TabBar仅在首页的AppBar中配置,其他页面无此配置
        bottom: TabBar(
          controller: _tabController,
          tabs: _topTabs,
        ),
      ),
      // 切换顶部Tab仅更新当前首页的body
      body: TabBarView(
        controller: _tabController,
        children: _topTabPages,
      ),
    );
  }
}

核心逻辑说明

  • 全局底部导航由父级嵌套路由承载,所有子路由页面共享显示,无需重复配置
  • 顶部TabBar为首页独有组件,切换底部导航到其他页面时,整个body被替换为无TabBar配置的其他页面,自然不会展示顶部Tab
  • 顶部Tab切换仅作用于首页内部的body区域,不修改路由栈,性能更高

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 09:36:03