Flutter如何实现跨页面共用appBar与bottomNavigationBar组件
核心实现逻辑
你需要做一个独立的共用导航父容器页面,这个页面本身是一个完整的Scaffold,自带你抽离的通用appBar和bottomNavigationBar,body区域作为子页面的渲染插槽,和React中Header、Footer中间夹路由的逻辑完全一致。因为你首页需要是欢迎页,只需要把欢迎页和这个父容器作为同级路由配置即可,不需要把父容器套在首页外层。
具体实现步骤
1. 新建共用导航父容器
父容器为StatefulWidget,内部管理底部导航选中状态,支持两种子页面渲染模式:
import 'package:flutter/material.dart'; // 导入你抽离的通用导航组件、各业务子页面 import 'nav_bar.dart'; import 'home_page.dart'; import 'scan_passport.dart'; import 'setting_page.dart'; class MainContainer extends StatefulWidget { const MainContainer({super.key}); @override State<MainContainer> createState() => _MainContainerState(); } class _MainContainerState extends State<MainContainer> { int _selectedIndex = 0; // 模式1:固定Tab页预加载,适合底部导航对应固定3-5个主页面的场景,切换流畅度最高 final List<Widget> _tabPages = const [ HomePage(), ScanPassport(), SettingPage(), ]; void _onItemTapped(int index) { setState(() { _selectedIndex = index; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: navBar(), // 你的通用AppBar组件 // 模式2:嵌套路由模式,对标React路由插槽,支持body内任意路由跳转 // 要使用这个模式就注释掉下面的_tabPages引用,替换为这个Navigator组件 // body: Navigator( // initialRoute: '/home', // onGenerateRoute: (settings) { // Widget currentPage; // switch(settings.name) { // case '/home': currentPage = const HomePage(); break; // case '/scan': currentPage = const ScanPassport(); break; // case '/setting': currentPage = const SettingPage(); break; // default: currentPage = const HomePage(); // } // return MaterialPageRoute(builder: (context) => currentPage, settings: settings); // }, // ), body: _tabPages[_selectedIndex], bottomNavigationBar: BottomNavigationBar( currentIndex: _selectedIndex, onTap: _onItemTapped, showSelectedLabels: false, showUnselectedLabels: false, type: BottomNavigationBarType.fixed, // 配置你的底部导航Item items: const [ BottomNavigationBarItem(icon: Icon(Icons.home), label: '首页'), BottomNavigationBarItem(icon: Icon(Icons.document_scanner), label: '扫描'), BottomNavigationBarItem(icon: Icon(Icons.settings), label: '设置'), ], ), ); } }
2. 配置全局路由
在main.dart中配置路由,初始路由设置为欢迎页,主容器作为独立路由存在:
void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Demo', initialRoute: '/welcome', // 初始加载欢迎页 routes: { '/welcome': (context) => const WelcomePage(), // 你的欢迎页 '/main': (context) => const MainContainer(), // 共用导航主容器 }, ); } }
3. 欢迎页跳转逻辑
欢迎页完成引导后,调用路由跳转进入主容器,建议使用pushReplacementNamed禁止用户回退到欢迎页:
// 放在欢迎页的确认/进入按钮点击事件中 Navigator.pushReplacementNamed(context, '/main');
扩展说明
- 如果需要自定义单个子页面的AppBar内容(比如改标题、加右侧按钮),可以给你抽离的
navBar组件加动态配置参数,通过状态管理或者子页面回调同步当前页面的配置即可 - 如果需要某个子页面隐藏共用导航,只需要在父容器中添加bool类型控制变量,通过状态修改控制
appBar和bottomNavigationBar的显隐 - 使用嵌套路由模式时,子页面内的跳转调用
Navigator.of(context)只会操作内部路由栈,不会隐藏外层的共用导航,和你在React中的使用习惯完全一致
内容的提问来源于stack exchange,提问作者Jed
相关产品推荐
相关产品推荐

