HarmonyOS应用开发实战:萌宠日记 - 组件与标题栏控制

前言

Navigation 是 HarmonyOS 中最重要的 导航容器组件 之一,它集成了 标题栏页面栈转场动画 等核心能力。在 萌宠日记 中,Navigation 组件与 TabsNavPathStackNavDestination 配合使用,构建了完整的双层导航体系。

本文将从 萌宠日记 的 Navigation 使用出发,深入解析组件的标题栏控制、属性配置、与 NavPathStack 的协作,以及不同 Tab 下的标题栏显示策略。

一、Navigation 组件概述

1.1 组件定位

Navigation 组件在萌宠日记中扮演着 Tab 内部导航容器 的角色:

层级 组件 职责
第一层 Tabs 底部导航栏,管理 5 个 Tab 的切换
第二层 Navigation 每个 Tab 内部的导航容器,管理子页面栈
第三层 NavDestination 子页面容器,渲染目标页面
typescript 复制代码
// Index.ets --- 5 个 Tab 各自绑定一个 Navigation
// Tab 1: 首页
TabContent() {
  Navigation(this.homeStack) {
    HomePage({...})
  }
  .hideTitleBar(true)                       // 首页隐藏标题栏
  .navDestination(this.HomeNavDestinations)  // 注册子页面
}

// Tab 2: 日记
TabContent() {
  Navigation(this.diaryStack) {
    WriteDiaryPage()
  }
  .hideTitleBar(false)                      // 日记显示标题栏
  .navDestination(this.DiaryNavDestinations)
}

// Tab 3: 记录
TabContent() {
  Navigation(this.recordStack) {
    HealthRecordPage({...})
  }
  .hideTitleBar(false)                      // 记录显示标题栏
  .navDestination(this.RecordNavDestinations)
}

// Tab 4: 统计
TabContent() {
  Navigation(this.statsStack) {
    StatisticsPage()
  }
  .hideTitleBar(false)
}

// Tab 5: 我的
TabContent() {
  Navigation(this.profileStack) {
    ProfilePage()
  }
  .hideTitleBar(false)
}

提示 :每个 Navigation 实例绑定独立的 NavPathStack,实现 Tab 间导航栈的完全隔离。hideTitleBar 属性控制根页面是否显示标题栏,子页面通过 NavDestination 的 title 属性单独控制。

二、标题栏控制

2.1 hideTitleBar 属性

typescript 复制代码
// 隐藏标题栏
Navigation(this.homeStack) {
  HomePage({...})
}
.hideTitleBar(true)  // 首页隐藏标题栏,让内容区域更大

// 显示标题栏
Navigation(this.diaryStack) {
  WriteDiaryPage()
}
.hideTitleBar(false)  // 日记页显示标题栏

2.2 标题栏显示策略

Tab hideTitleBar 根页面标题栏 子页面标题栏 设计理由
首页 true 隐藏 由 NavDestination 控制 首页内容丰富,需要更多空间
日记 false 显示 由 NavDestination 控制 编辑器需要明确的界面标识
记录 false 显示 由 NavDestination 控制 需要清晰的功能区分
统计 false 显示 ---(无子页面) 统计页独立展示
我的 false 显示 ---(无子页面) 个人中心需要标题

2.3 标题栏组成

Navigation 的标题栏由以下元素组成:

复制代码
┌─────────────────────────────────────────┐
│  ‹ 返回按钮  │  标题文字    │  (右侧操作区)  │
└─────────────────────────────────────────┘
元素 说明 控制方式
返回按钮 自动显示(当页面栈深度 > 1 时) hideTitleBar 控制
标题文字 页面标题 NavDestination 的 title 属性
右侧操作区 自定义操作按钮 通过 title 自定义构建

三、Navigation 的属性配置

3.1 核心属性

typescript 复制代码
Navigation(this.homeStack) {
  HomePage({...})
}
.hideTitleBar(true)                                       // 隐藏标题栏
.navDestination(this.HomeNavDestinations)                  // 子页面注册
.titleMode(NavigationTitleMode.MINI)                       // 标题栏模式
.backButtonIcon($r('app.media.back'))                      // 自定义返回图标
.onAppear(() => { console.log('Navigation appeared') })    // 出现回调
.onDisappear(() => { console.log('Navigation disappeared') }) // 消失回调

3.2 属性对照表

属性 类型 默认值 萌宠日记配置
hideTitleBar boolean false 首页 true,其他 false
navDestination @Builder --- 每个 Tab 各自的 @Builder
titleMode NavigationTitleMode FREE 未配置
backButtonIcon ResourceStr 默认返回箭头 未配置
onAppear 回调 --- 未配置
onDisappear 回调 --- 未配置

四、标题栏模式

4.1 三种模式

typescript 复制代码
// 自由模式(默认)
Navigation(this.homeStack) {
  HomePage()
}
.titleMode(NavigationTitleMode.FREE)

// 迷你模式
Navigation(this.homeStack) {
  HomePage()
}
.titleMode(NavigationTitleMode.MINI)

// 全屏模式
Navigation(this.homeStack) {
  HomePage()
}
.titleMode(NavigationTitleMode.FULL)
模式 说明 适用场景
FREE 标题栏可滚动,随内容滚动而隐藏/显示 内容消费型页面
MINI 小标题模式,紧凑显示 工具型页面
FULL 大标题模式,显眼突出 首页、欢迎页

4.2 萌宠日记的选择

萌宠日记未显式配置 titleMode,使用默认的 FREE 模式,因为:

  • 首页已隐藏标题栏,不需要设置
  • 其他 Tab 的标题栏使用默认模式即可满足需求
  • 保持配置简洁,减少不必要的属性设置

五、子页面标题栏控制

typescript 复制代码
// 子页面的标题栏由 NavDestination 控制
@Builder
HomeNavDestinations() {
  NavDestination() {
    PetProfilePage()
  }
  .title('宠物档案')  // 子页面标题

  NavDestination() {
    GrowthTimelinePage()
  }
  .title('成长时间轴')

  NavDestination() {
    CommunityPage()
  }
  .title('发现')
}

5.2 标题栏继承关系

复制代码
Navigation.hideTitleBar = true
    ↓
根页面:标题栏隐藏(根据 hideTitleBar)
    ↓
用户跳转到子页面(pushPath)
    ↓
子页面 NavDestination:标题栏由 NavDestination 控制
    ↓
如果 NavDestination 设置了 title 属性 → 显示标题栏
如果 NavDestination 设置了 hideTitleBar(true) → 隐藏标题栏

六、Navigation 的生命周期

6.1 生命周期回调

typescript 复制代码
Navigation(this.homeStack) {
  HomePage({...})
}
.hideTitleBar(true)
.navDestination(this.HomeNavDestinations)
.onAppear(() => {
  // Navigation 组件出现时触发
  console.log('Home Navigation appeared')
})
.onDisappear(() => {
  // Navigation 组件消失时触发
  console.log('Home Navigation disappeared')
})

6.2 生命周期与 Tab 切换

事件 Navigation 回调 说明
Tab 首次选中 onAppear Navigation 首次渲染
Tab 切换出去 --- Navigation 实例保持,不解构
Tab 切换回来 --- Navigation 实例已存在,不触发 onAppear
应用退出 onDisappear Navigation 销毁

七、Navigation 与路由结合

7.1 路由跳转方式

typescript 复制代码
// 方式一:通过 NavPathStack 跳转(推荐)
this.homeStack.pushPath({ name: 'petProfile' })

// 方式二:通过 router 跳转(全局路由)
router.pushUrl({ url: 'pages/SomePage' })

// 方式三:通过 Navigation 的 NavPathStack 跳转
this.homeStack.pushPath({ name: 'community' })

7.2 路由方式对比

对比维度 NavPathStack router
导航范围 当前 Navigation 内部 全局页面栈
标题栏 自动管理 需手动处理
页面栈 独立栈 全局栈
推荐场景 Tab 内子页面 跨模块跳转

八、标题栏自定义

8.1 自定义标题

typescript 复制代码
// 通过 NavDestination 的 title 属性自定义标题栏
NavDestination() {
  PetProfilePage()
}
.title('宠物档案')  // 简单文字标题

8.2 自定义标题栏样式

typescript 复制代码
// 自定义标题栏构建
NavDestination() {
  PetProfilePage()
}
.title({
  text: '宠物档案',
  icon: $r('app.media.pet_icon')
})
.hideTitleBar(false)

九、Navigation 与 Tabs 的协作

9.1 协作架构

复制代码
Tabs(底部导航)
├── TabContent 0(首页)
│   └── Navigation(homeStack)
│       ├── HomePage(根页面,标题栏隐藏)
│       ├── PetProfilePage(子页面,标题栏显示)
│       ├── GrowthTimelinePage(子页面,标题栏显示)
│       └── CommunityPage(子页面,标题栏显示)
├── TabContent 1(日记)
│   └── Navigation(diaryStack)
│       ├── WriteDiaryPage(根页面,标题栏显示)
│       └── 更多子页面(可扩展)
├── TabContent 2(记录)
│   └── Navigation(recordStack)
│       ├── HealthRecordPage(根页面,标题栏显示)
│       ├── AlbumPage(子页面,标题栏显示)
│       └── ReminderPage(子页面,标题栏显示)
├── TabContent 3(统计)
│   └── Navigation(statsStack)
│       └── StatisticsPage(根页面,标题栏显示)
└── TabContent 4(我的)
    └── Navigation(profileStack)
        └── ProfilePage(根页面,标题栏显示)

9.2 协作优势

优势 说明
导航隔离 每个 Tab 的页面栈互不干扰
标题栏独立 每个 Tab 的标题栏独立控制
灵活扩展 任意 Tab 可独立增加子页面
状态保持 Tab 切换时页面状态自动保持

十、最佳实践

10.1 标题栏设计原则

  • 首页通常隐藏标题栏,让内容区域更大
  • 内容型页面显示标题栏,提供明确的导航上下文
  • 子页面通过 NavDestination 的 title 属性设置标题
  • 标题文字简洁明了,不超过 6 个字

10.2 常见问题

问题 原因 解决方案
标题栏不显示 hideTitleBar 设置为 true 设置为 false 或检查 NavDestination 的 title
返回按钮不显示 页面栈深度为 1(根页面) 只有子页面才显示返回按钮
标题栏闪烁 Navigation 与 Tab 切换冲突 检查 Navigation 的 hideTitleBar 是否与 Tab 切换冲突
标题栏高度异常 安全区域未适配 系统默认处理安全区域

总结

本文从 萌宠日记Navigation 组件 使用出发,深入解析了标题栏控制的完整实现:

  1. 组件定位:Tab 内部导航容器,管理子页面栈
  2. 标题栏控制:hideTitleBar 属性控制根页面标题栏
  3. 标题栏组成:返回按钮、标题文字、右侧操作区
  4. 标题栏模式:FREE、MINI、FULL 三种模式
  5. 子页面标题:NavDestination 的 title 属性单独控制
  6. 生命周期:onAppear 和 onDisappear 回调
  7. 路由结合:NavPathStack 与 router 的对比
  8. 与 Tabs 协作:完整的双层导航架构

Navigation 组件是 HarmonyOS 导航体系的核心,掌握其属性配置和标题栏控制,是构建专业级应用导航体验的关键。

下一篇我们将深入 页面间数据传递 --- 回调函数模式,解析父子组件之间的通信机制。

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

相关推荐
Larcher18 小时前
React Router 不只是页面跳转:从 SPA 路由到权限守卫的完整实践
javascript·后端
Larcher18 小时前
大模型为什么每次回答都不一样?一文搞懂 Temperature、Top K 与 Top P
javascript·后端
LucianaiB20 小时前
毕业老学长给我留的最后一句话是:“AI 写的,别挂我名。” 我直接 神(Seed Evolving) 来!助我!
后端
IvanCodes20 小时前
RAG 实战教程(一):RAG 工作原理与完整流程——分片、索引、召回、重排和生成
人工智能·后端·agent
CodeSheep21 小时前
稚晖君公司人事大变动,来了!
前端·后端·程序员
小满zs21 小时前
Go语言第八章(函数)
后端·go
stark张宇1 天前
实战Go高级特性:Context超时控制、defer资源回收与Channel通信的关键避坑点
后端·go
凤山老林1 天前
Spring Boot @Async 线上实战:从默认配置到生产级线程池治理
java·spring boot·后端
IT_陈寒1 天前
Vue的响应式让我原地破防,原来问题出在这
前端·人工智能·后端
思考着亮1 天前
1.RabbitMQ基本使用
后端