使用Flutter导航组件TabBar、AppBar等为鸿蒙应用程序构建完整的应用导航体系

使用Flutter导航组件TabBar、AppBar等为鸿蒙应用程序构建完整的应用导航体系

📖 前言

导航是移动应用中最重要的功能之一,它帮助用户在不同页面和功能之间切换。Flutter 提供了丰富的导航组件,包括 AppBarBottomNavigationBarTabBarDrawerScaffold 等,能够构建完整的应用导航体系。

image-20260126231922533

🎯 导航组件概览

Flutter 提供了以下导航组件:

组件名功能说明适用场景
Scaffold页面骨架应用页面基础结构
AppBar顶部导航栏页面标题、操作按钮
BottomNavigationBar底部导航栏主要功能切换
TabBar标签栏页面内内容分类
TabBarView标签内容区标签对应的内容
Drawer侧边抽屉导航菜单、设置
BackButton返回按钮页面返回
CloseButton关闭按钮关闭对话框

🏗️ Scaffold 组件

Scaffold 是 Material Design 应用的基础结构,提供了页面骨架。

基础用法

Scaffold( appBar:AppBar( title:Text('标题'),), body:Center( child:Text('页面内容'),),)
image-20260126231956561

完整结构

Scaffold( appBar:AppBar(title:Text('标题')), body:Center(child:Text('内容')), drawer:Drawer(child:ListView(...)), bottomNavigationBar:BottomNavigationBar(...), floatingActionButton:FloatingActionButton(...),)
image-20260126232023830

📱 AppBar 组件

AppBar 是顶部导航栏,提供标题、返回按钮、操作按钮等功能。

基础用法

AppBar( title:Text('应用标题'), actions:[IconButton( icon:Icon(Icons.search), onPressed:(){},),],)
image-20260126232054774

自定义样式

AppBar( title:Text('标题'), backgroundColor:Colors.blue, foregroundColor:Colors.white, elevation:0, actions:[IconButton(icon:Icon(Icons.more_vert), onPressed:(){}),],)
image-20260126232117126

带 TabBar 的 AppBar

DefaultTabController( length:3, child:Scaffold( appBar:AppBar( title:Text('标题'), bottom:TabBar( tabs:[Tab(text:'标签1'),Tab(text:'标签2'),Tab(text:'标签3'),],),), body:TabBarView( children:[Center(child:Text('内容1')),Center(child:Text('内容2')),Center(child:Text('内容3')),],),),)
image-20260126232155387

📍 BottomNavigationBar 组件

BottomNavigationBar 是底部导航栏,用于主要功能切换。

基础用法

classMyHomePageextendsStatefulWidget{@override _MyHomePageState createState()=>_MyHomePageState();}class _MyHomePageState extendsState<MyHomePage>{ int _currentIndex =0;@overrideWidgetbuild(BuildContext context){returnScaffold( body:_getPage(_currentIndex), bottomNavigationBar:BottomNavigationBar( currentIndex: _currentIndex, onTap:(index){setState((){ _currentIndex = index;});}, items:[BottomNavigationBarItem( icon:Icon(Icons.home), label:'首页',),BottomNavigationBarItem( icon:Icon(Icons.search), label:'搜索',),BottomNavigationBarItem( icon:Icon(Icons.person), label:'我的',),],),);}Widget_getPage(int index){switch(index){case0:returnHomePage();case1:returnSearchPage();case2:returnProfilePage();default:returnHomePage();}}}
image-20260126232216123

自定义样式

BottomNavigationBar( currentIndex: _currentIndex, onTap:(index){setState((){ _currentIndex = index;});}, selectedItemColor:Colors.blue, unselectedItemColor:Colors.grey, type:BottomNavigationBarType.fixed, items:[BottomNavigationBarItem( icon:Icon(Icons.home), label:'首页',),BottomNavigationBarItem( icon:Icon(Icons.search), label:'搜索',),],)
image-20260126232234802

📑 TabBar 和 TabBarView 组件

TabBarTabBarView 用于创建标签页导航。

基础用法

DefaultTabController( length:3, child:Scaffold( appBar:AppBar( title:Text('标题'), bottom:TabBar( tabs:[Tab(text:'标签1'),Tab(text:'标签2'),Tab(text:'标签3'),],),), body:TabBarView( children:[Center(child:Text('内容1')),Center(child:Text('内容2')),Center(child:Text('内容3')),],),),)
image-20260126233509850

自定义 TabBar 样式

TabBar( tabs:[Tab(text:'标签1'),Tab(text:'标签2'),], labelColor:Colors.blue, unselectedLabelColor:Colors.grey, indicatorColor:Colors.blue, indicatorWeight:3,)
image-20260126235736083

🗂️ Drawer 组件

Drawer 是侧边抽屉,用于导航菜单和设置。

基础用法

Scaffold( appBar:AppBar(title:Text('标题')), drawer:Drawer( child:ListView( padding:EdgeInsets.zero, children:[DrawerHeader( decoration:BoxDecoration(color:Colors.blue), child:Text('菜单标题'),),ListTile( leading:Icon(Icons.home), title:Text('首页'), onTap:(){Navigator.pop(context);},),ListTile( leading:Icon(Icons.settings), title:Text('设置'), onTap:(){Navigator.pop(context);},),],),), body:Center(child:Text('内容')),)
image-20260126233703443

自定义 Drawer 样式

Drawer( child:Column( children:[Container( height:200, decoration:BoxDecoration( gradient:LinearGradient( colors:[Colors.blue,Colors.purple],),), child:Center( child:Column( mainAxisAlignment:MainAxisAlignment.center, children:[CircleAvatar( radius:40, child:Icon(Icons.person, size:40),),SizedBox(height:16),Text('用户名', style:TextStyle(color:Colors.white)),],),),),Expanded( child:ListView( children:[ListTile( leading:Icon(Icons.home), title:Text('首页'), onTap:(){},),Divider(),ListTile( leading:Icon(Icons.settings), title:Text('设置'), onTap:(){},),],),),],),)
image-20260126235806228

💡 实际应用场景

场景1:主页面导航结构

classMainPageextendsStatefulWidget{@override _MainPageState createState()=>_MainPageState();}class _MainPageState extendsState<MainPage>{ int _currentIndex =0;@overrideWidgetbuild(BuildContext context){returnScaffold( appBar:AppBar( title:Text('应用名称'), actions:[IconButton( icon:Icon(Icons.search), onPressed:(){},),],), drawer:_buildDrawer(), body:_getPage(_currentIndex), bottomNavigationBar:BottomNavigationBar( currentIndex: _currentIndex, onTap:(index){setState((){ _currentIndex = index;});}, items:[BottomNavigationBarItem( icon:Icon(Icons.home), label:'首页',),BottomNavigationBarItem( icon:Icon(Icons.favorite), label:'收藏',),BottomNavigationBarItem( icon:Icon(Icons.person), label:'我的',),],),);}Widget_buildDrawer(){returnDrawer( child:ListView( children:[ListTile( leading:Icon(Icons.home), title:Text('首页'), onTap:(){Navigator.pop(context);setState((){ _currentIndex =0;});},),ListTile( leading:Icon(Icons.settings), title:Text('设置'), onTap:(){Navigator.pop(context);},),],),);}Widget_getPage(int index){switch(index){case0:returnHomePage();case1:returnFavoritePage();case2:returnProfilePage();default:returnHomePage();}}}
image-20260126235835810

场景2:详情页导航

Scaffold( appBar:AppBar( title:Text('详情页'), leading:BackButton(), actions:[IconButton( icon:Icon(Icons.share), onPressed:(){},),IconButton( icon:Icon(Icons.more_vert), onPressed:(){},),],), body:SingleChildScrollView( child:Column( children:[// 内容],),),)
image-20260126235901528

场景3:标签页导航

DefaultTabController( length:3, child:Scaffold( appBar:AppBar( title:Text('分类'), bottom:TabBar( tabs:[Tab(text:'推荐'),Tab(text:'热门'),Tab(text:'最新'),],),), body:TabBarView( children:[RecommendPage(),HotPage(),LatestPage(),],),),)
image-20260126235925531

⚠️ 常见问题与解决方案

问题1:BottomNavigationBar 切换时页面重建

解决方案

  • 使用 IndexedStack 保持页面状态
  • 使用状态管理库管理页面状态

问题2:TabBar 和 TabBarView 不同步

解决方案

  • 使用 TabController 手动控制
  • 确保 DefaultTabControllerlength 正确

问题3:Drawer 无法打开

解决方案

  • 确保 Scaffolddrawer 属性
  • 检查是否有其他组件遮挡
  • 使用 Scaffold.of(context).openDrawer() 手动打开

💼 最佳实践

1. 导航状态管理

classNavigationStateextendsChangeNotifier{ int _currentIndex =0; int get currentIndex => _currentIndex;voidchangeIndex(int index){ _currentIndex = index;notifyListeners();}}

2. 统一导航样式

classAppNavigation{staticAppBarbuildAppBar(String title,{List<Widget>? actions}){returnAppBar( title:Text(title), actions: actions, elevation:0,);}staticBottomNavigationBarbuildBottomNav( int currentIndex,Function(int) onTap,){returnBottomNavigationBar( currentIndex: currentIndex, onTap: onTap, type:BottomNavigationBarType.fixed, items:[BottomNavigationBarItem(icon:Icon(Icons.home), label:'首页'),BottomNavigationBarItem(icon:Icon(Icons.search), label:'搜索'),BottomNavigationBarItem(icon:Icon(Icons.person), label:'我的'),],);}}

📚 总结

通过本教程,我们学习了:

  1. Scaffold 页面骨架的使用
  2. AppBar 顶部导航栏的使用
  3. BottomNavigationBar 底部导航栏的使用
  4. TabBarTabBarView 标签页的使用
  5. Drawer 侧边抽屉的使用
  6. ✅ 实际应用场景和最佳实践

导航组件是 Flutter 应用的基础,掌握好这些组件的用法,能够让你的应用导航更加完善和用户友好!


🔗 相关资源

Happy Coding! 🎨✨
欢迎加入开源鸿蒙跨平台社区

Read more

【前端】使用Vue3过程中遇到加载无效设置点击方法提示不存在的情况,原来是少加了一个属性

【前端】使用Vue3过程中遇到加载无效设置点击方法提示不存在的情况,原来是少加了一个属性

🌹欢迎来到《小5讲堂》🌹 🌹这是《前端》系列文章,每篇文章将以博主理解的角度展开讲解。🌹 🌹温馨提示:博主能力有限,理解水平有限,若有不对之处望指正!🌹 目录 * 前言 * 提示报错 * 问题分析 * 1. **Options API vs Composition API 风格差异** * ✅ **Options API 写法(方法直接放在外面)** * ✅ **Composition API 写法(方法必须在 setup 中定义)** * ✅ **`<script setup>` 语法糖(最简洁的 Composition API)** * 2. **为什么你的代码会报错?** * 3. **解决方案** * 方案 1:改用 **Options API**(适合从 Vue

从2025看2026前端发展趋势

🎨 从2025看2026前端发展趋势 一、📌 核心前言(2025铺垫→2026展望) 2025年前端行业已完成“基础成熟化”:Vue3、React18成为主流,TypeScript全面普及,工程化流程趋于完善,AI工具开始渗透开发环节,但也暴露了痛点——开发效率不均衡、跨端体验不一致、AI与业务结合浅显、性能优化门槛高。 ✨ 核心趋势:2026年前端将从「基础成熟」走向「深度融合」,重点围绕「AI原生开发」「跨端统一」「性能极致」「工程化提效」四大方向突破,同时Node.js等底层工具的升级(如2026年Node.js新特性)将进一步推动前端向全栈化、平台化转型。 二、✍️ 五大核心趋势(手绘重点·结合2025现状) 1. AI原生开发:从“辅助工具”到“核心生产力” 🤖(最重磅) (1)2025现状 2025年,前端AI工具多为“辅助层面”

Telegram bot & Mini-App开发实践---Telegram简单介绍与初始化小程序获取window.Telegram.WebApp对象并解析

Telegram bot & Mini-App开发实践---Telegram简单介绍与初始化小程序获取window.Telegram.WebApp对象并解析

➡️【好看的灵魂千篇一律,有趣的鲲志一百六七!】- 欢迎认识我~~作者:鲲志说(公众号、B站同名,视频号:鲲志说996)科技博主:极星会 星辉大使后端研发:java、go、python、TS,前电商、现web3主理人:COC杭州开发者社区主理人 、周周黑客松杭州主理人、AI爱好者: AI电影共创社杭州核心成员、阿里蚂蚁校友会技术AI分会副秘书长博客专家:阿里云专家博主;ZEEKLOG博客专家、后端领域新星创作者、内容合伙人 今天是2024年10月24日,又是一年1024程序员节。和往常一样,平淡的度过了一天,又和往常不一样,收到了人生第一束花花🌹值得纪念。就像两年前毅然决然的从电商行业进入一个零基础零认知的web3世界一样,都有第一次的刻骨铭心,选择了就勇敢的做下去,开花结果是期待,但过程也十分重要。也像2016年下半年第一次注册ZEEKLOG去检索问题的解决方案,经过多番查阅实践,终于解决;更像2017年9月27日我的第一篇ZEEKLOG博客文章潦草问世,当初不追求得到什么,只把ZEEKLOG文章当作是学习笔记,知识总结,一路写写停停,不知不觉间也悄然过去了7个年头,断然想不到博

OpenClaw 中 web_search + web_fetch 最佳实践速查表

OpenClaw 中 web_search + web_fetch 最佳实践速查表

OpenClaw 中 web_search + web_fetch 最佳实践速查表 摘要:本文帮助读者明确 OpenClaw 网络搜索工具和不同搜索技能的的职责边界,理解“先搜索、再抓取、后总结”的最佳实践,并能更稳定地在 OpenClaw 中使用 tavily-search 与 web_fetch 完成网络信息搜索任务。主要内容包括:解决 OpenClaw 中 web_search、tavily-search、web_fetch、原生 provider 与扩展 skill 容易混淆的问题、网络搜索能力分层说明、OpenClaw 原生搜索 provider 与 Tavily/Firecrawl 扩展 skill 的区别、标准工作流、提示词模板、