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
相关产品推荐
相关产品推荐

