欢迎光临
我们一直在努力

「高山流水遇知音」HarmonyOS NEXT 应用开发实战 — ArkTS墨国风交互设计

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

摘要:本文以「高山流水遇知音」鸿蒙原生应用为案例,从架构设计、ArkUI 组件化开发、@Builder 自定义构建函数、@State 状态管理、条件渲染、路由导航、水墨风格主题配色等多个维度,深度解析基于 HarmonyOS NEXT API 24(SdkVersion 6.1.1)的 ArkTS 应用开发全流程。全文包含完整源码分析、设计模式解读及构建部署实战,适合 1~3 年经验的鸿蒙开发者阅读。


目录

  • 项目背景与文化内涵
  • 开发环境与 API 24 特性
  • 系统架构设计
  • ArkTS 页面结构详解
  • @Builder 自定义构建函数实战
  • @State 状态管理机制
  • 条件渲染与交互反馈
  • 路由导航系统
  • 水墨国风主题设计系统
  • 核心组件 API 解析
  • 构建部署与签名配置
  • 全文总结与技术展望

  • 1. 项目背景与文化内涵

    1.1 「高山流水」的千年回响

    "高山流水"是中国文化中最著名的知音典故,出自《列子·汤问》:

    伯牙善鼓琴,钟子期善听。伯牙鼓琴,志在高山,钟子期曰:"善哉,峨峨兮若泰山!"志在流水,钟子期曰:“善哉,洋洋兮若江河!”

    伯牙与子期的故事穿越两千五百年的时空,成为中国人心目中"知音"的终极象征。而"知音"一词——从最初"懂得琴音的人",逐步演化为"真正理解自己内心世界的人"——折射出中国人对精神共鸣与心灵相通的至高追求。

    1.2 为什么用鸿蒙原生应用来讲述中国故事?

    在 HarmonyOS NEXT 全场景智慧生态中,文化类应用拥有独特的价值空间:

    • 沉浸式体验:原生 ArkUI 渲染引擎提供流畅的动画与交互,适合呈现有质感的叙事内容
    • 跨设备流转:API 24 强化了跨端能力,同一应用可在手机、平板、折叠屏间无缝适配
    • 国际化潜力:鸿蒙全球化布局下,用数字技术传播中国文化具有天然优势
    • 性能优势:ArkTS 的静态类型系统与 AOT 编译优化,让复杂 UI 渲染保持高性能

    1.3 应用功能定位

    本应用是 Demo0611_1 项目中的第三个子应用,聚焦于:

    • 以卡片化叙事呈现伯牙子期典故的五个维度
    • 通过点击切换 + 古籍原文展开的交互模式,兼顾阅读沉浸感与信息层次
    • 采用水墨国风深色调视觉语言,营造古雅氛围
    • 作为主页面 3 个导航应用之一,展示 HarmonyOS 多页面导航能力

    2. 开发环境与 API 24 特性

    2.1 开发工具链配置

    配置项值
    IDE DevEco Studio NEXT
    SDK 版本 HarmonyOS NEXT API 24
    SdkVersion 6.1.1(24)
    开发语言 ArkTS(基于 TypeScript 的声明式 UI 语言)
    构建工具 hvigor(鸿蒙原生构建系统)
    目标设备 phone(手机形态)
    运行时 OS HarmonyOS

    2.2 API 24 关键特性

    从 build-profile.json5 的产物配置可以看到:

    {
    "products": [
    {
    "name": "default",
    "signingConfig": "default",
    "targetSdkVersion": "6.1.1(24)",
    "compatibleSdkVersion": "6.1.1(24)",
    "runtimeOS": "HarmonyOS",
    }
    ]
    }

    API 24(对应 SdkVersion 6.1.1)是 HarmonyOS NEXT 的重要里程碑,相较于早期版本,在以下方面有显著增强:

  • ArkUI 声明式语法稳定化:组件 API 趋于稳定,@Builder 参数传递不再受限
  • Router 路由增强:支持更灵活的参数传递与生命周期回调
  • 字体与排版系统升级:letterSpacing、lineHeight 等排版属性全面支持
  • Shadow API 标准化:shadow() 属性支持 radius、color、offsetX/Y 结构化参数
  • 条件渲染优化:if/else 条件渲染性能提升,减少不必要的节点重建
  • 安全签名体系完善:基于 ECDSA 的签名机制与密钥管理
  • 2.3 API 24 与 API 12 的关键差异对比

    特性API 12(HarmonyOS 4.x)API 24(HarmonyOS NEXT 6.1.1)
    语言 eTS / ArkTS 混合 纯 ArkTS
    @Styles 部分支持 全面支持全局样式复用
    @Builder 参数受限 完整参数传递
    shadow() 简版 结构化参数(radius/color/offset)
    Router router.push router.pushUrl(增强版)
    字体间距 有限 letterSpacing 完整支持
    条件渲染 性能一般 优化节点缓存
    编译 解释执行 AOT + JIT 双模式

    3. 系统架构设计

    3.1 项目总体架构

    Demo0611_1/
    ├── entry/
    │ ├── src/main/
    │ │ ├── ets/
    │ │ │ ├── entryability/
    │ │ │ │ └── EntryAbility.ets ← 应用入口Ability
    │ │ │ └── pages/
    │ │ │ ├── Index.ets ← 主页面(导航聚合)
    │ │ │ ├── FutureTech.ets ← 子应用1:未来技术
    │ │ │ ├── PersonalPlan.ets ← 子应用2:个人规划
    │ │ │ └── GaoshanLiushui.ets ← 子应用3:高山流水(本文主题)
    │ │ ├── resources/
    │ │ │ └── base/
    │ │ │ └── profile/
    │ │ │ └── main_pages.json ← 页面路由注册
    │ │ └── module.json5 ← 模块配置
    │ └── build-profile.json5 ← 构建配置(含签名)
    ├── build-profile.json5 ← 项目级构建配置
    └── hvigor-config.json5 ← hvigor 构建配置

    3.2 页面路由注册机制

    在 main_pages.json 中注册页面路由:

    {
    "src": [
    "pages/Index",
    "pages/GaoshanLiushui"
    ]
    }

    这里的 pages/GaoshanLiushui 是路由标记,对应 ets/pages/GaoshanLiushui.ets 文件。$profile:main_pages 在 module.json5 中引用:

    "pages": "$profile:main_pages"

    3.3 单页面组件架构(GaoshanLiushui.ets)

    GaoshanLiushui (struct)
    ├── @State selectedIndex: number = -1 ← 当前选中的卡片索引
    ├── @State showPoem: boolean = false ← 是否显示古籍原文
    ├── private storySections: StorySection[] ← 故事数据源(5条)
    │
    ├── @Builder storyCard(item, index) ← 自定义卡片构建函数
    │ └── Column
    │ ├── Text (icon)
    │ ├── Text (title)
    │ ├── Divider (条件变色)
    │ ├── Text (content)
    │ └── if (selected && showPoem) ← 条件渲染
    │ └── Column (古籍原文区域)
    │
    └── build()
    ├── Row (顶部导航栏:← 返回)
    ├── Column (标题区域:高山流水·遇知音)
    ├── Divider (分隔装饰)
    ├── if (selectedIndex === -1) ← 引导提示(条件渲染)
    │ └── Column (点击提示)
    ├── Scroll (可滚动故事列表)
    │ └── Column
    │ └── ForEach (5张卡片循环)
    │ └── storyCard(item, index)
    ├── Column (底部落款)


    4. ArkTS 页面结构详解

    4.1 页面入口与装饰器

    @Entry
    @Component
    struct GaoshanLiushui {
    // …
    }

    • @Entry:标记该组件为页面入口,允许通过路由跳转加载
    • @Component:声明这是一个自定义组件,可被组合到其他组件中
    • struct GaoshanLiushui:使用 struct(结构体)而非 class 定义组件,这是 ArkTS 组件的最佳实践——struct 是值类型,内存分配在栈上,性能优于 class

    4.2 数据接口定义

    interface StorySection {
    title: string
    icon: string
    content: string
    poem: string
    color: string
    }

    ArkTS 的 interface 在编译时进行类型擦除,不产生运行时开销。这是与 TypeScript 的重要区别——ArkTS 更接近静态语言的类型系统。

    4.3 组件状态变量

    @State selectedIndex: number = –1;
    @State showPoem: boolean = false;

    @State 是 ArkUI 响应式系统的核心装饰器。当被装饰变量变化时,框架自动重新渲染依赖该变量的组件子树。这里:

    • selectedIndex = -1 表示未选中任何卡片,此时显示引导提示
    • showPoem = false 表示默认不展开古籍原文

    4.4 构建函数 build()

    build() 是每个 @Component 的必需方法,描述组件的 UI 结构:

    build() {
    Column() {
    // 1. 顶部导航栏
    Row() { … }
    // 2. 标题区域
    Column() { … }
    // 3. 分隔线
    Divider()
    // 4. 引导提示(条件渲染)
    if (this.selectedIndex === –1) { … }
    // 5. 可滚动故事列表
    Scroll() { … }
    // 6. 底部落款
    Column() { … }
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#120E0A')
    }

    关键设计决策:使用最外层 Column 作为根容器而非 Stack,因为页面需要从上到下依次排列导航栏、标题、分隔线、列表和底部落款,天然符合列布局的语义。


    5. @Builder 自定义构建函数实战

    5.1 定义与语法

    @Builder
    storyCard(item: StorySection, index: number) {
    Column() {
    // 卡片内容
    }
    // 卡片样式
    }

    @Builder 是 ArkUI 提供的自定义构建函数装饰器,用于封装可复用的 UI 片段。与普通函数相比,@Builder 具有以下特性:

  • 可接收参数:支持传参,参数类型可以是基础类型、接口或组件
  • 可包含状态逻辑:内部可读取外部 @State 变量
  • 声明式语法:内部必须使用声明式 UI 描述(不能有副作用操作)
  • 无返回值:@Builder 不返回组件引用,而是直接嵌入调用处的组件树
  • 5.2 调用方式

    ForEach(this.storySections,
    (item: StorySection, index: number) => {
    this.storyCard(item, index)
    },
    (item: StorySection) => item.title)

    这里的关键点:

    • ForEach 是 ArkUI 的列表循环组件,接收三个参数:

    • 数据源数组:this.storySections
    • 子组件生成函数:(item, index) => this.storyCard(item, index)
    • 键值生成函数:(item) => item.title — 用于 Diff 算法的 key
    • 调用 @Builder 时使用 this.storyCard(item, index) 格式(非 new 关键字),表明这是组件树的原地展开

    5.3 为什么使用 @Builder 而非自定义 @Component?

    对比维度@Builder自定义 @Component
    复用范围 当前 struct 内 跨文件全局复用
    参数传递 直接传参(按值) @Prop / @Link 装饰
    性能开销 几乎为零(内联展开) 有组件实例化开销
    状态隔离 共享外部状态 独立状态空间
    适用场景 同页面内的 UI 片段封装 跨页面复用的独立组件

    在本应用中,storyCard 只需要在该页面内复用,且需要直接访问 this.selectedIndex 和 this.showPoem 两个状态变量,使用 @Builder 是最优选择。

    5.4 @Builder 内部状态读取机制

    @Builder
    storyCard(item: StorySection, index: number) {
    // …
    Divider()
    .width('40%')
    .color(this.selectedIndex === index ? item.color : '#4A3C30')
    // ^^ 读取当前 struct 的 @State 变量
    // …
    .backgroundColor(this.selectedIndex === index ? '#2A2018' : '#1E1814')
    .border({
    color: this.selectedIndex === index ? item.color + '66' : '#3A2C20',
    })
    .shadow(this.selectedIndex === index ? {
    radius: 12,
    color: item.color + '33',
    offsetX: 0,
    offsetY: 4
    } : undefined)
    }

    当 @State selectedIndex 变化时,ArkUI 框架自动追踪到所有依赖 selectedIndex 的 @Builder 调用,仅重新渲染受影响的节点,而非整个列表。这是 ArkUI 细粒度响应式更新的核心优势。


    6. @State 状态管理机制

    6.1 状态驱动的交互模型

    用户点击卡片
    ↓
    onClick 触发
    ↓
    修改 this.selectedIndex / this.showPoem
    ↓
    ArkUI 框架检测 @State 变化
    ↓
    Diff 算法比较虚拟 DOM 树
    ↓
    增量更新受影响的 UI 节点

    6.2 点击事件的状态逻辑

    .onClick(() => {
    if (this.selectedIndex === index) {
    // 点击已选中卡片:切换古籍原文的显示状态
    this.showPoem = !this.showPoem;
    } else {
    // 点击新卡片:切换到新卡片,默认展开原文
    this.selectedIndex = index;
    this.showPoem = true;
    }
    })

    这个状态逻辑实现了三个交互场景:

    场景操作状态变化视觉效果
    初始态 任意卡片 selectedIndex = index, showPoem = true 卡片高亮 + 原文展开
    已选中态 再次点击同一卡片 showPoem = !showPoem 切换原文显示/隐藏
    切换卡片 点击另一张 selectedIndex = newIndex, showPoem = true 原卡片恢复 + 新卡片高亮展开

    6.3 @State 的响应式边界

    注意到以下代码:

    storyCard(item: StorySection, index: number) {
    // …
    }

    @Builder 接收的参数 item 和 index 是按值传递的普通参数,而不是状态变量。这意味着:

  • 修改 item.color 不会触发 UI 重新渲染
  • 修改 index 也不会触发 UI 重新渲染
  • 只有外部的 @State selectedIndex 和 @State showPoem 变化才会驱动卡片 UI 更新
  • 这是 ArkTS 响应式设计的核心原则:只有 @State/@Prop/@Link 等装饰器标记的变量才具有响应性。


    7. 条件渲染与交互反馈

    7.1 引导提示条件渲染

    if (this.selectedIndex === –1) {
    Column() {
    Text('🪷')
    .fontSize(36)
    Text('点击章节 · 品读千古知音故事')
    .fontSize(14)
    .fontColor('#6A5A4A')
    .letterSpacing(2)
    Text('再点击已选中章节 · 展开/收起古籍原文')
    .fontSize(12)
    .fontColor('#4A3A2A')
    }
    .width('100%')
    .padding(16)
    }

    当 selectedIndex === -1(未选中任何卡片)时,显示莲花图标和操作引导文案。一旦用户点击任意卡片,该区域自动消失——这是通过 ArkUI 的条件渲染实现的。

    7.2 古籍原文的区域条件渲染

    if (this.selectedIndex === index && this.showPoem) {
    Column() {
    Divider().color('#4A3C30').width('80%').margin({ bottom: 8 })
    Text('—— 「古籍摘录」——')
    .fontSize(11)
    .fontColor(item.color)
    Text(item.poem)
    .fontSize(13)
    .fontColor('#D0C0A8')
    .lineHeight(24)
    }
    }

    这个条件嵌套了两层判断:

  • this.selectedIndex === index — 确保只有在当前卡片被选中时才可能显示
  • this.showPoem — 控制显示/隐藏的开关
  • 条件渲染的注意事项:

    • ArkUI 的 if/else 渲染在条件为 false 时,对应的组件节点会从组件树中移除(而非隐藏),这节省了内存
    • 因此 showPoem 从 true 变为 false 时,古籍原文内容消失,再次变为 true 时会重新创建节点
    • 对于频繁切换的场景,使用 Visibility 属性(Visibility.Hidden)替代条件渲染可能更优

    7.3 条件样式变化

    在卡片样式中使用了大量三元表达式来实现条件驱动的视觉反馈:

    // 分割线颜色:选中时变为章节主题色
    .color(this.selectedIndex === index ? item.color : '#4A3C30')

    // 背景色:选中时变亮,产生浮起效果
    .backgroundColor(this.selectedIndex === index ? '#2A2018' : '#1E1814')

    // 边框颜色:选中时变为半透明主题色
    .color(this.selectedIndex === index ? item.color + '66' : '#3A2C20')

    // 阴影:仅在选中时显示
    .shadow(this.selectedIndex === index ? {
    radius: 12,
    color: item.color + '33',
    offsetX: 0,
    offsetY: 4
    } : undefined)

    注意 undefined 的巧妙使用——当条件不满足时,shadow(undefined) 表示不应用阴影效果。


    8. 路由导航系统

    8.1 主页面导航

    在 Index.ets 中,通过 router.pushUrl 实现页面跳转:

    import router from '@ohos.router';

    Button('高山流水遇知音 →')
    .onClick(() => {
    router.pushUrl({ url: 'pages/GaoshanLiushui' });
    })

    8.2 子页面返回

    在 GaoshanLiushui.ets 的顶部导航栏中:

    Text('← 返回')
    .fontSize(15)
    .fontColor('#A09080')
    .letterSpacing(1)
    .onClick(() => {
    router.back();
    })

    router.back() 返回上一页,不需要参数。如果需要返回到指定页面并传递数据,可以使用 router.back({ url: 'pages/Index', params: { from: 'GaoshanLiushui' } })。

    8.3 页面生命周期

    当使用 router.pushUrl 跳转时,页面栈如下:

    Index (主页) ← 用户启动
    ↓ pushUrl('pages/GaoshanLiushui')
    GaoshanLiushui (当前页)
    Index (在栈中)
    ↓ router.back()
    Index (回到主页,GaoshanLiushui 出栈)

    ArkUI 页面生命周期方法包括:

    方法触发时机
    onPageShow() 页面显示时(包括从后台返回)
    onPageHide() 页面隐藏时(跳转到其他页面)
    onBackPress() 用户点击系统返回键时

    9. 水墨国风主题设计系统

    9.1 配色方案

    本应用采用了精心设计的深色调国风配色体系:

    色名色值用途设计理念
    宣纸底色 #120E0A 页面背景 仿古宣纸质感,微暖底调
    墨色 #A09080 正文/导航文字 灰调墨色,不刺眼
    浅墨 #6A5A4A 引导提示文字 更淡的墨色,视觉后退
    淡金 #C9A96E 标题/高亮 仿金色印章与题字
    默卡背 #1E1814 卡片默认背景 比背景略亮,建立层次
    亮卡背 #2A2018 选中卡片背景 浮起效果
    边框暗 #3A2C20 默认卡片边框 含混边界
    落款色 #5A4A3A 底部文字 浅淡落款

    9.2 五个章节的主题色体系

    每个故事卡片拥有独立的主题色,形成节奏变化:

    color: '#C9A96E' // 琴师伯牙 — 金色,代表琴艺的高贵
    color: '#6B8E6B' // 樵知音子期 — 青绿,代表山林樵夫
    color: '#C04040' // 高山流水 — 朱红,代表炽烈的情感
    color: '#8B6FA0' // 知音文化 — 紫色,代表文化沉淀
    color: '#D4A853' // 千古传承 — 明黄,代表传承的光辉

    9.3 排版系统

    // 大标题:书法感,大字号 + 宽字距
    Text('高山流水')
    .fontSize(32)
    .fontWeight(FontWeight.Bold)
    .letterSpacing(8)

    // 副标题:金色 + 更宽字距
    Text('遇 知 音')
    .fontSize(20)
    .fontColor('#C9A96E')
    .letterSpacing(12) // 12px 字距,每字之间留白

    // 正文:小字号 + 适中行距
    Text(item.content)
    .fontSize(13)
    .fontColor('#A09080')
    .lineHeight(22)

    // 古籍原文:暖色 + 舒适行距
    Text(item.poem)
    .fontSize(13)
    .fontColor('#D0C0A8')
    .lineHeight(24)

    排版设计要点:

  • 字距(letterSpacing):大标题使用 8px 字距,"遇 知 音"使用 12px 字距,模拟书法作品中字与字之间的呼吸感
  • 行距(lineHeight):正文 22px、古诗 24px,在 13px 字号下提供舒适的阅读间距(约 1.7~1.85 倍行高)
  • 字号层级:32px (标题) → 20px (副标题) → 14px (引导) → 13px (正文) → 12/10px (辅助),形成清晰的视觉层级

  • 10. 核心组件 API 解析

    10.1 Column 容器组件

    Column() {
    // 子组件…
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#120E0A')
    .padding({ top: 8, bottom: 8 })

    API 参数详解:

    • .width('100%') / .height('100%):百分比尺寸,相对于父容器
    • .backgroundColor('#120E0A'):十六进制颜色值,支持 6 位(#RRGGBB)和 8 位(#RRGGBBAA)格式
    • .padding({ left, right, top, bottom }):内边距,支持统一值或分别指定

    10.2 Text 文本组件

    Text('高山流水')
    .fontSize(32)
    .fontWeight(FontWeight.Bold)
    .fontColor('#F0E8D8')
    .letterSpacing(8)
    .textAlign(TextAlign.Center)
    .lineHeight(22)

    API 参数详解:

    • fontSize(value: number | string):字号,支持 number(vp 单位)或 Resource($r('app.float.xxx'))
    • fontWeight(value: FontWeight):字重枚举,包括 FontWeight.Bold、FontWeight.Medium、FontWeight.Normal 等
    • fontColor(value: ResourceColor):字体颜色,支持 string(十六进制)、number(ARGB)、Resource 三种形式
    • letterSpacing(value: number):字符间距,正值为拉开,负值为紧缩
    • textAlign(value: TextAlign):文字对齐方式,TextAlign.Start/Center/End
    • lineHeight(value: number | string):行高,影响多行文本的行间距

    10.3 Divider 分割线组件

    Divider()
    .width('40%')
    .color('#C9A96E44')
    .margin({ top: 4, bottom: 8 })

    API 参数详解:

    • .width(value: string | number):分割线的宽度(长度),百分比值相对于父容器宽度
    • .color(value: ResourceColor):分割线颜色,支持半透明色值(如 #C9A96E44 中 44 为 26.7% 透明度)
    • .margin(value: Margin | number):外边距

    10.4 Scroll 滚动容器

    Scroll() {
    Column() {
    ForEach(…)
    }
    .width('100%')
    .padding({ left: 16, right: 16 })
    }
    .layoutWeight(1)
    .width('100%')

    关键设计:

    • .layoutWeight(1):这是 ArkUI 中的权重布局机制。外层 Column 在分配垂直空间时,给 Scroll 分配 “1 份” 弹性空间,剩余高度由其他固定高度的子组件(导航栏、标题、底部落款)占用。这确保了 Scroll 占满中间所有可用空间,不会溢出。
    • Scroll 默认方向为垂直滚动,无需显式指定 scrollable(ScrollDirection.Vertical)

    10.5 ForEach 循环渲染

    ForEach(
    this.storySections, // 数据源
    (item: StorySection, index: number) => { // 子组件生成
    this.storyCard(item, index)
    },
    (item: StorySection) => item.title // 键值生成
    )

    三参数详解:

  • arr: Array<T>:数据源数组,支持 Array 类型(包括 ReadonlyArray 和普通数组)
  • itemGenerator: (item: T, index?: number) => void:子组件生成函数,返回值为 void(直接在函数体内调用子组件)
  • keyGenerator: (item: T, index?: number) => string:键值生成函数,返回唯一标识字符串。ArkUI 使用该键值执行 Diff 算法,当数组发生增删改时,只更新变化的部分
  • 键值选择的重要性:

    • 使用 item.title 作为 key(如 '琴师伯牙'),是稳定的、唯一的字符串
    • 避免使用数组 index 作为 key,因为数组调整顺序时 index 会变,导致不必要的 DOM 重建
    • 避免使用随机数或时间戳作为 key,因为每次渲染都会生成新 key,破坏 Diff 算法的优化

    10.6 Button 按钮组件

    Button('高山流水遇知音 →')
    .fontSize(16)
    .fontWeight(FontWeight.Medium)
    .fontColor('#F0E8D8')
    .backgroundColor('#C9A96E')
    .borderRadius(24)
    .width(240)
    .height(48)
    .margin({ top: 16 })
    .shadow({
    radius: 8,
    color: '#C9A96E66',
    offsetX: 0,
    offsetY: 4
    })
    .onClick(() => {
    router.pushUrl({ url: 'pages/GaoshanLiushui' });
    })

    shadow API 结构化参数:

    参数类型说明
    radius number 阴影模糊半径,越大越模糊
    color ResourceColor 阴影颜色,支持半透明
    offsetX number 水平偏移量(正右负左)
    offsetY number 垂直偏移量(正下负上)

    这是 API 24 新增的结构化 shadow API,相较于早期版本的 shadow(value: number)(仅支持模糊半径),提供了更丰富的阴影控制能力。

    10.7 Row 行容器与 layoutWeight

    Row() {
    Text('← 返回')
    .fontSize(15)
    .fontColor('#A09080')
    .letterSpacing(1)
    .onClick(() => { router.back(); })
    Text(' ')
    .layoutWeight(1)
    // ^^^^^^^^^^^^ 占据剩余空间,将返回按钮"推到"左侧
    }
    .width('100%')

    这里的 Text(' ').layoutWeight(1) 是一个弹性占位符的技巧——一个空白文本占据所有剩余空间,使得 ← 返回 左对齐。这与传统的 justifyContent(FlexAlign.SpaceBetween) 效果类似,但 layoutWeight 提供了更精确的空间分配控制。


    11. 构建部署与签名配置

    11.1 构建配置详解

    build-profile.json5 是鸿蒙应用的构建配置文件,核心配置项包括:

    {
    "app": {
    "signingConfigs": […], // 签名配置(调试 + 发布)
    "products": [
    {
    "name": "default",
    "signingConfig": "default", // 使用 default 签名
    "targetSdkVersion": "6.1.1(24)", // 目标 API 版本
    "compatibleSdkVersion": "6.1.1(24)", // 兼容最低版本
    "runtimeOS": "HarmonyOS", // 目标 OS
    "buildOption": {
    "strictMode": {
    "caseSensitiveCheck": true, // 严格模式:大小写敏感检查
    "useNormalizedOHMUrl": true // 使用规范化 OHM URL
    }
    }
    }
    ],
    "buildModeSet": [
    { "name": "debug" }, // 调试模式
    { "name": "release" } // 发布模式
    ]
    },
    "modules": [
    {
    "name": "entry",
    "srcPath": "./entry",
    "targets": [
    {
    "name": "default",
    "applyToProducts": ["default"]
    }
    ]
    }
    ]
    }

    11.2 签名机制

    本应用使用 HarmonyOS 原生签名(type: “HarmonyOS”),基于 ECDSA(椭圆曲线数字签名算法):

    签名配置项值说明
    签名类型 HarmonyOS(原生签名,非 OpenHarmony)
    证书文件 .cer — X.509 格式数字证书
    配置文件 .p7b — PKCS#7 签名属性文件
    密钥库文件 .p12 — PKCS#12 格式密钥库
    密钥别名 debugKey — 调试密钥别名
    签名算法 SHA256withECDSA — 安全哈希 + 椭圆曲线签名

    11.3 构建命令

    # 调试模式构建 HAP
    hvigorw assembleHap –no-daemon –build-mode debug

    # 构建成功后输出路径
    entry/build/default/outputs/default/
    └── entry-default-unsigned.hap

    完整构建日志解读:

    UP-TO-DATE :entry:default@PreBuild… ← 预构建(缓存命中)
    UP-TO-DATE :entry:default@CompileArkTS… ← ArkTS 编译为 JS 字节码
    UP-TO-DATE :entry:default@CompileResource… ← 资源文件编译
    UP-TO-DATE :entry:default@PackageHap… ← 打包 HAP
    UP-TO-DATE :entry:default@SignHap… ← HAP 签名
    UP-TO-DATE :entry:default@CollectDebugSymbol…← 收集调试符号
    BUILD SUCCESSFUL in 4s 578ms ← 构建成功

    “UP-TO-DATE” 表示该任务由于未检测到文件变化而使用了缓存,这大大缩短了增量构建的时间。首次构建时,这些步骤将显示为 “EXECUTING” 并花费更多时间。


    12. 全文总结与技术展望

    12.1 技术要点回顾

    通过「高山流水遇知音」应用的完整开发,我们实践了 HarmonyOS NEXT API 24 的以下核心技术:

    技术领域核心技术点应用场景
    组件架构 @Entry + @Component + struct 页面组件定义
    状态管理 @State 装饰器 + 响应式更新 卡片选中/原文展开/收起
    自定义构建 @Builder 函数 + 参数传递 故事卡片 UI 封装
    列表渲染 ForEach + 键值生成器 5 章节数据循环展示
    条件渲染 if/else 状态驱动 引导提示 / 古籍原文区域
    路由导航 router.pushUrl / router.back 页面跳转与返回
    布局系统 Column/Row + layoutWeight 垂直布局与弹性空间
    排版 fontSiz/letterSpacing/lineHeight 国风书法感排版
    视觉反馈 shadow + border + backgroundColor 条件变化 卡片选中态浮起效果
    构建配置 build-profile.json5 / 签名机制 调试与发布构建

    12.2 可以继续深化的方向

  • 动画系统:可引入 @Animatable 和 transition 实现卡片展开/收起时的平滑动画
  • 手势交互:添加滑动手势(PanGesture)实现卡片间滑动切换
  • 数据持久化:使用 @ohos.data.preferences 保存用户阅读进度
  • 多语言支持:通过 $r('app.string.xxx') 资源引用实现中英文切换
  • 无障碍:添加 accessibilityText 属性,提升视障用户的使用体验
  • 性能优化:使用 LazyForEach(虚拟列表)替换 ForEach,在更多数据场景下提升滚动性能
  • 12.3 鸿蒙生态下的文化数字传播

    "高山流水遇知音"不仅是一个技术演示项目,更是用原生应用传承中华文化的一次尝试。在鸿蒙生态加速建设的当下,文化类应用的价值愈发凸显:

    • 技术 + 文化:ArkUI 的声明式框架让精致 UI 的开发效率大幅提升
    • 一次开发,多端部署:同一代码可适配手机、平板、折叠屏、车机等设备
    • 原生性能,极致体验:ArkTS AOT 编译确保流畅的动画和渲染性能

    附录

    A. 完整源码清单

    GaoshanLiushui.ets(254 行)

    核心文件,包含页面全部逻辑与 UI 代码。代码组织分三层:

  • 顶部:import 导入、interface 定义、struct 定义 + 状态变量 + 数据源
  • 中间:@Builder storyCard 自定义构建函数
  • 底部:build() 页面布局函数,按导航栏 → 标题 → 故事列表 → 落款顺序组织
  • Index.ets(89 行)

    主页导航页面,包含三个按钮:

    • 未来技术发展方向(红色主题 #FF6C6C)
    • 个人未来 3~5 年规划(蓝色主题 #1E90FF)
    • 高山流水遇知音(金色主题 #C9A96E)

    main_pages.json

    {
    "src": [
    "pages/Index",
    "pages/GaoshanLiushui"
    ]
    }

    B. API 24 已弃用 / 不再推荐的方法

    在编写代码时请注意以下 API 24 的兼容性变化:

    旧写法(不推荐)推荐写法(API 24)
    router.push({ uri: 'xxx' }) router.pushUrl({ url: 'xxx' })
    flexWrap: FlexWrap.Wrap .flexWrap(FlexWrap.Wrap)
    shadow(radius: number) shadow({ radius: number, color: Color, offsetX/Y: number })
    @State deepObj = { a: { b: 1 } } 使用 @Observed + @ObjectLink 深度监听

    API 版本:HarmonyOS NEXT API 24 (SdkVersion 6.1.1)

    赞(0)
    未经允许不得转载:171主机测评 » 「高山流水遇知音」HarmonyOS NEXT 应用开发实战 — ArkTS墨国风交互设计
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址