HarmonyOS应用《玄象》开发实战:底部导航栏 BottomTabBar 封装与 @Builder 复用
阅读时长:约 19 分钟 | 难度:★★★★☆ | 篇章:第 3 篇 · 首页与功能导航
对应源码:entry/src/main/ets/common/components/BottomTabBar.ets、HomePage.ets中的BottomNavBarBuilder
前言
底部导航栏是移动端首页的标配。玄象项目底部导航栏包含"首页、探索、我的"三个标签,通过@Builder封装为BottomNavBar,并在公共组件层提供独立的BottomTabBar组件。本篇将深入剖析玄象项目底部导航栏的实现:从BottomTabBar公共组件设计、@Builder复用、@State currentIndex选中态切换,到 TabItem 接口、点击事件处理、布局属性配置。掌握这套底部导航栏实现方法论,您就能为任何 HarmonyOS 应用打造标准化的底部导航。
提示:玄象项目底部导航栏使用 emoji 图标 + 文字标签的经典组合,通过选中态颜色变化强化交互反馈。
一、玄象项目底部导航栏两种实现
1.1 HomePage 内的 BottomNavBar Builder
@BuilderBottomNavBar(){Row(){this.TabItem('🏠','首页',0)this.TabItem('🧭','探索',1)this.TabItem('👤','我的',2)}.width('100%').height(60).backgroundColor(Colors.BG_CARD).border({width:{top:1},color:Colors.BG_CARD_BORDER})}@BuilderTabItem(icon:string,name:string,index:number){Column({space:4}){Text(icon).fontSize(22).fontColor(index===this.currentTab?Colors.PRIMARY_GOLD:Colors.TEXT_DIM)Text(name).fontSize(11).fontColor(index===this.currentTab?Colors.PRIMARY_GOLD:Colors.TEXT_DIM)}.layoutWeight(1).height(56).justifyContent(FlexAlign.Center).onClick(()=>{this.currentTab=index;if(index===2){router.pushUrl({url:'pages/profile/ProfilePage'});}})}1.2 common/components 中的 BottomTabBar 组件
@Componentexportstruct BottomTabBar{@StatecurrentIndex:number=0;@Statetabs:TabItem[]=[];privateonTabChange?:(index:number)=>void;build(){Row(){ForEach(this.tabs,(item:TabItem,index:number)=>{Column({space:4}){Text(item.icon).fontSize(24).fontColor(index===this.currentIndex?Colors.PRIMARY_GOLD:Colors.TEXT_DIM)Text(item.name).fontSize(11).fontColor(index===this.currentIndex?Colors.PRIMARY_GOLD:Colors.TEXT_DIM)}.layoutWeight(1).height(56).justifyContent(FlexAlign.Center).onClick(()=>{this.currentIndex=index;if(this.onTabChange){this.onTabChange(index);}})},(item:TabItem)=>item.name)}.width('100%').height(60).backgroundColor(Colors.BG_CARD).border({width:{top:1},color:Colors.BG_CARD_BORDER})}}二、两种实现的对比
2.1 设计差异
| 维度 | HomePage BottomNavBar | common BottomTabBar |
|---|---|---|
| 形式 | @Builder | @Componentstruct |
| 数据 | 硬编码 3 个标签 | tabs数组动态配置 |
| 状态 | currentTab | currentIndex |
| 事件 | 直接 router.pushUrl | onTabChange回调 |
| 复用 | 仅 HomePage | 全应用 |
2.2 共同点
- 高度 60vp(内容区 56vp + 上下间距)
- 背景色
Colors.BG_CARD - 顶部 1vp 分割线
Colors.BG_CARD_BORDER - 选中态金色
Colors.PRIMARY_GOLD - 未选中态灰色
Colors.TEXT_DIM - 选中态颜色切换逻辑
三、TabItem 接口设计
3.1 BottomTabBar 中的 TabItem
interfaceTabItem{name:string;icon:string;page:string;}3.2 字段说明
| 字段 | 类型 | 含义 |
|---|---|---|
name | string | 标签文字 |
icon | string | 图标(emoji 或字符) |
page | string | 跳转页面路由(可选) |
3.3 数据驱动设计
玄象项目BottomTabBar组件采用数据驱动设计:
@Statetabs:TabItem[]=[];// 使用方初始化 tabsthis.tabs=[{name:'首页',icon:'🏠',page:'pages/HomePage'},{name:'探索',icon:'🧭',page:'pages/ExplorePage'},{name:'我的',icon:'👤',page:'pages/profile/ProfilePage'}];四、@State currentIndex 选中态
4.1 状态定义
@StatecurrentIndex:number=0;玄象项目用currentIndex标记当前选中的标签索引。
4.2 选中态颜色切换
Text(item.icon).fontColor(index===this.currentIndex?Colors.PRIMARY_GOLD:Colors.TEXT_DIM)Text(item.name).fontColor(index===this.currentIndex?Colors.PRIMARY_GOLD:Colors.TEXT_DIM)通过三元表达式动态切换颜色:
- 选中(
index === currentIndex):金色PRIMARY_GOLD - 未选中:灰色
TEXT_DIM
4.3 点击切换状态
.onClick(()=>{this.currentIndex=index;if(this.onTabChange){this.onTabChange(index);}})点击 Tab 时:
- 更新
currentIndex,触发颜色切换。 - 调用
onTabChange回调,通知外部。
五、@Builder 复用详解
5.1 @Builder 参数传递
@BuilderTabItem(icon:string,name:string,index:number){// ...}@Builder支持参数传递,玄象项目通过参数复用TabItemBuilder。
5.2 @Builder 内部访问外部状态
@BuilderTabItem(icon:string,name:string,index:number){Text(icon).fontColor(index===this.currentTab?Colors.PRIMARY_GOLD:Colors.TEXT_DIM)// ↑ this.currentTab 访问外层 @State}@Builder内部可直接访问外层组件的@State变量。
5.3 @Builder vs @Component
| 维度 | @Builder | @Component |
|---|---|---|
| 复用范围 | 同组件 | 跨组件 |
| 状态 | 共享外层 | 独立 @State |
| 性能 | 略低 | 高 |
| 适用 | 简单片段 | 复杂组件 |
提示:玄象项目首页用
@Builder实现BottomNavBar,是因为导航栏与首页耦合度高。未来若多页面共享导航栏,应提取为@Component。
六、底部导航栏视觉规范
6.1 尺寸规范
| 元素 | 尺寸 |
|---|---|
| 导航栏高度 | 60vp |
| 内容区高度 | 56vp |
| 图标字号 | 22-24vp |
| 标签字号 | 11vp |
| 上下间距 | 4vp |
6.2 颜色规范
| 状态 | 图标颜色 | 文字颜色 |
|---|---|---|
| 选中 | Colors.PRIMARY_GOLD | Colors.PRIMARY_GOLD |
| 未选中 | Colors.TEXT_DIM | Colors.TEXT_DIM |
6.3 布局规范
┌──────────────────────────────────┐ │ 分割线 (top: 1) │ ├────────┬────────┬────────┤ │ 🏠 │ 🧭 │ 👤 │ ← icon │ 首页 │ 探索 │ 我的 │ ← name └────────┴────────┴────────┘七、底部导航栏的扩展
7.1 添加徽标
Badge({count:5,position:BadgePosition.RightTop}){Text(item.icon).fontSize(24)}7.2 添加中间凸起按钮
Row(){this.TabItem('🏠','首页',0)this.TabItem('🧭','探索',1)// 中间凸起按钮Image($r('app.media.add')).width(40).height(40).margin({top:-20})this.TabItem('👤','我的',2)}7.3 使用 Tabs 组件替代
Tabs(){TabContent(){HomePage()}.tabBar('首页')TabContent(){ExplorePage()}.tabBar('探索')TabContent(){ProfilePage()}.tabBar('我的')}八、玄象项目 BottomTabBar 调用示例
8.1 在页面中使用 BottomTabBar
import{BottomTabBar}from'../common/components/BottomTabBar';@Entry@Componentstruct HomePage{privatetabs:TabItem[]=[{name:'首页',icon:'🏠',page:'pages/HomePage'},{name:'探索',icon:'🧭',page:'pages/ExplorePage'},{name:'我的',icon:'👤',page:'pages/profile/ProfilePage'}];build(){Column(){// 内容区Scroll(){...}// 底部导航栏BottomTabBar({tabs:this.tabs,currentIndex:0,onTabChange:(index:number)=>{router.pushUrl({url:this.tabs[index].page});}})}}}8.2 组件复用价值
- 代码复用:所有需要底部导航的页面复用
BottomTabBar。 - 视觉一致:导航栏样式统一。
- 行为一致:选中态切换逻辑一致。
九、底部导航栏的交互细节
9.1 点击反馈
玄象项目当前未实现点击反馈动画。可扩展为:
@StateclickIndex:number=-1;Text(item.icon).scale({x:this.clickIndex===index?0.9:1,y:this.clickIndex===index?0.9:1}).animation({duration:100}).onClick(()=>{this.clickIndex=index;setTimeout(()=>{this.clickIndex=-1;},100);this.currentIndex=index;})9.2 防止重复点击
privatelastClickTime:number=0;.onClick(()=>{constnow=Date.now();if(now-this.lastClickTime<500)return;// 500ms 防抖this.lastClickTime=now;this.currentIndex=index;if(this.onTabChange){this.onTabChange(index);}})十、玄象项目导航体系总结
10.1 三层导航
| 层级 | 实现位置 |
|---|---|
| 页面级导航 | router.pushUrl/back |
| 首页九宫格导航 | FeatureGridBuilder |
| 底部导航栏 | BottomTabBar组件 |
10.2 导航视觉一致性
- 金色主题:
Colors.PRIMARY_GOLD - 深色背景:
Colors.BG_CARD - 卡片范式:
border+borderRadius
总结
本篇以玄象项目底部导航栏为蓝本,深入剖析了 ArkUI 底部导航实现:从BottomTabBar公共组件、TabItem接口设计、@Builder复用、@State currentIndex选中态切换,到点击事件处理、视觉规范、扩展方向。掌握这套底部导航栏实现方法论,您就能为任何 HarmonyOS 应用打造标准化的底部导航。
下一篇:《28 · Scroll 容器 + layoutWeight 的弹性滚动布局》,将带您深入玄象项目首页可滚动区的实现。
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
- HarmonyOS 官方文档:BottomTabBar 设计
- HarmonyOS 官方文档:Tabs 组件
- HarmonyOS 官方文档:Badge 组件
- 开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net