古诗小集开发实战:从零开发一款 HarmonyOS 古诗鉴赏应用

古诗小集:从零开发一款 HarmonyOS 古诗鉴赏应用

一、缘起

中国古典诗词是中华文化的瑰宝,千百年来传诵不衰。从李白的「床前明月光」到杜甫的「两个黄鹂鸣翠柳」,这些短短数十字的诗句承载着深邃的情感与哲思。作为一名开发者,我一直想做一款轻量、优雅的古诗鉴赏应用,让用户在碎片时间里能够随时翻阅经典,感受诗词之美。

恰逢 HarmonyOS 生态日趋成熟,ArkTS 语言与 ArkUI 框架为快速构建跨设备应用提供了强大的支持。本文将以「古诗小集」应用为例,详细讲解如何使用 HarmonyOS 6.1 SDK(API 23)开发一款完整的古诗阅读应用,涵盖项目初始化、数据建模、页面路由、UI 设计、构建打包等全流程。

二、项目概览

「古诗小集」是一个轻量级的古诗鉴赏应用,核心功能非常简单:

  • 古诗列表页:以列表形式展示收录的古诗,显示标题、作者与朝代信息
  • 古诗详情页:点击任意古诗进入详情页,展示原文(居中大字排版)以及详细的注释与译文

应用目前收录了 8 首脍炙人口的唐诗:

  1. 李白《静夜思》
  2. 孟浩然《春晓》
  3. 王之涣《登鹳雀楼》
  4. 贺知章《咏柳》
  5. 李白《望庐山瀑布》
  6. 杜甫《绝句》
  7. 李白《早发白帝城》
  8. 柳宗元《江雪》

这 8 首诗覆盖了写景、抒情、咏物、哲理等多种题材,极具代表性。后续可以轻松扩展至数百首,形成一个完整的古诗词库。

三、技术选型与项目初始化

3.1 技术栈

技术 选择 版本
开发工具 DevEco Studio 6.1
开发语言 ArkTS 6.1
UI 框架 ArkUI 6.1
目标 SDK HarmonyOS SDK API 23
构建工具 Hvigor 内置
包管理 Ohpm 内置

HarmonyOS 6.1 对应的应用模型为 Stage 模型,这是 HarmonyOS 自 API 9 起主推的应用开发模型,具有更好的组件化能力和生命周期管理。

3.2 项目结构

复制代码
app6115/
├── AppScope/
│   ├── app.json5                  # 应用级配置(包名、版本号、图标等)
│   └── resources/
│       └── base/element/string.json
├── entry/
│   ├── build-profile.json5         # 模块构建配置
│   ├── oh-package.json5            # 模块依赖声明
│   └── src/main/
│       ├── ets/
│       │   ├── entryability/EntryAbility.ets  # 应用 Ability 入口
│       │   ├── model/PoemData.ets             # 古诗数据模型
│       │   └── pages/
│       │       ├── Index.ets                  # 古诗列表页
│       │       └── PoemDetailPage.ets         # 古诗详情页
│       ├── module.json5            # 模块清单文件
│       └── resources/
│           └── base/
│               ├── element/       # 字符串、颜色、尺寸资源
│               ├── media/         # 图片资源
│               └── profile/       # 路由配置
├── build-profile.json5            # 项目级构建配置
├── hvigor/                        # Hvigor 构建配置
└── oh-package.json5               # 项目级依赖

3.3 关键配置文件

AppScope/app.json5 定义了应用的基本信息:

json 复制代码
{
  "app": {
    "bundleName": "com.example.app6115",
    "vendor": "example",
    "versionCode": 1000000,
    "versionName": "1.0.0",
    "icon": "$media:layered_image",
    "label": "$string:app_name"
  }
}

这里的 bundleName 是应用的唯一标识符,类似于 Android 的 packageNamelabel 引用了资源文件中的字符串,这种方式有利于多语言适配。

entry/src/main/module.json5 定义了模块的 Ability 信息:

json 复制代码
{
  "module": {
    "name": "entry",
    "type": "entry",
    "mainElement": "EntryAbility",
    "deviceTypes": ["phone"],
    "pages": "$profile:main_pages",
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "label": "$string:EntryAbility_label",
        "startWindowIcon": "$media:startIcon",
        "exported": true,
        "skills": [
          {
            "entities": ["entity.system.home"],
            "actions": ["ohos.want.action.home"]
          }
        ]
      }
    ]
  }
}

其中 skills 字段声明了该 Ability 能够响应主屏启动意图,这是桌面图标点击启动应用的标配配置,不可或缺。

四、数据层设计

4.1 数据模型

model/PoemData.ets 中定义了古诗的数据结构:

typescript 复制代码
export interface Poem {
  id: number;
  title: string;
  author: string;
  dynasty: string;
  content: string;
  注释: string;
}

这里用一个有趣的设计细节:字段名直接使用了中文「注释」。ArkTS 完全支持 Unicode 标识符,所以中文变量名是合法且可运行的。在实际团队协作中,建议还是使用英文命名以保持一致性,但在个人项目中使用中文字段名可以让数据定义更加直观------看到字段就知道它的含义,无需额外的注释说明。

4.2 数据组织

应用将古诗数据定义为一个常数组 poemList,每首诗包含完整的原文和注释译文。以《静夜思》为例:

typescript 复制代码
{
  id: 1,
  title: '静夜思',
  author: '李白',
  dynasty: '唐',
  content: '床前明月光,\n疑是地上霜。\n举头望明月,\n低头思故乡。',
  注释: '【注释】①静夜思:安静的夜晚产生的思绪。②疑:好像...\n\n【译文】明亮的月光洒在床前...'
}

这种数据组织方式有以下优点:

  1. 自包含性:每首诗的数据完整独立,方便增删改查
  2. 可扩展性:可以轻松从 JSON 文件或网络 API 加载数据
  3. 低耦合:数据与 UI 分离,修改数据无需改动页面代码

五、页面开发详解

5.1 古诗列表页(Index.ets)

列表页是用户打开应用首先看到的界面,设计上追求简洁优雅的古风风格。

5.1.1 页面结构
复制代码
Column
├── Row          ------ 标题栏「古诗小集」
├── Text         ------ 副标题「收录经典古诗,品味千年韵味」
└── List         ------ 古诗列表
    └── ForEach
        └── ListItem
            └── Column
                ├── Row
                │   ├── Text       ------ 序号(金色圆底)
                │   ├── Column
                │   │   ├── Text   ------ 诗名
                │   │   └── Text   ------ 朝代·作者
                │   ├── Blank
                │   └── Text       ------ 箭头 ›
                └── (点击事件)
5.1.2 ForEach 的正确使用

在 ArkTS 中,ForEach 用于在容器组件内部循环渲染数据。其完整签名如下:

typescript 复制代码
ForEach(
  arr: any[],
  itemGenerator: (item: any, index?: number) => void,
  keyGenerator?: (item: any, index?: number) => string
)
  • arr:数据源数组
  • itemGenerator:列表项生成器,接收数组中的每个元素
  • keyGenerator(可选):键值生成器,用于列表高效更新

实际使用示例:

typescript 复制代码
List() {
  ForEach(this.poems, (item: Poem) => {
    ListItem() {
      // 每个列表项的 UI 定义
    }
    .padding({ left: 16, right: 16, bottom: 10 })
  }, (item: Poem) => item.id.toString())  // 以 id 作为唯一键
}

keyGenerator 不是必需的,但强烈建议提供。它可以帮助框架在数据更新时精确识别哪些列表项需要重新渲染,极大提升长列表的刷新性能。

5.1.3 样式与布局技巧

古风配色方案:

typescript 复制代码
// 背景色:米黄色
.backgroundColor('#FAF6EF')
// 标题栏:浅棕色
.backgroundColor('#F5EDE0')
// 主文字:深褐色
.fontColor('#3A2E1E')
// 辅助文字:中褐色
.fontColor('#8B7355')
// 强调色:金色
.fontColor('#C4A265')

卡片阴影效果:

typescript 复制代码
.shadow({
  radius: 4,
  color: '#20000000',
  offsetX: 0,
  offsetY: 2
})

这里的 color 使用十六进制 ARGB 格式,前两位 20 表示透明度为 12.5%(约 32/255),实现轻柔的阴影效果,不喧宾夺主。

5.1.4 页面跳转
typescript 复制代码
ListItem() {
  // ... 列表项内容
}
.onClick(() => {
  router.pushUrl({
    url: 'pages/PoemDetailPage',
    params: { poem: item }
  });
})

router.pushUrl 方法用于导航到目标页面,通过 params 字段传递参数。在 HarmonyOS 中,传递复杂对象时,框架会自动序列化和反序列化,开发者无需手动处理。

不过需要注意的是,从 HarmonyOS 6.1 开始,router.pushUrl 已标记为废弃(deprecated),推荐使用新的路由 API。但在当前版本中仍然可以正常工作,迁移到新 API 也很简单。

5.2 古诗详情页(PoemDetailPage.ets)

详情页是用户阅读古诗的核心页面,设计上力求沉浸式阅读体验。

5.2.1 页面结构
复制代码
Column
├── Row                  ------ 导航栏(返回按钮 + 标题)
└── Scroll
    └── Column
        ├── Column      ------ 诗题 + 作者信息(白色卡片)
        ├── Column      ------ 原文区域(居中大字排版)
        └── Column      ------ 注释与译文区域
5.2.2 参数接收
typescript 复制代码
@State poem: Poem = {} as Poem;

aboutToAppear(): void {
  const params = router.getParams() as Record<string, Object>;
  if (params) {
    this.poem = params['poem'] as Poem;
  }
}

aboutToAppear 是 ArkTS 的生命周期钩子,在页面即将显示时触发。在这里从路由参数中取出古诗数据并赋值给状态变量,ArkUI 会自动响应状态变化更新 UI。

需要注意的是,router.getParams() 同样已标记为废弃,推荐使用新的 getParams API,但当前版本依然兼容。

5.2.3 原文排版
typescript 复制代码
Text(this.poem.content)
  .fontSize(20)
  .fontColor('#3A2E1E')
  .lineHeight(36)       // 行高适当加大,增强可读性
  .letterSpacing(2)     // 字间距略宽,营造古风韵味
  .textAlign(TextAlign.Center)  // 居中排版
  .width('100%')

几个设计要点:

  1. 行高 = 36fp:相对于 20fp 的字号,约 1.8 倍行距,比常见的 1.5 倍更大,营造疏朗的阅读感受
  2. 字间距 = 2fp:适度加宽字间距,模拟古籍排版的效果
  3. 居中排版:古诗短小精悍,居中排版更符合传统书法作品的视觉习惯
5.2.4 注释区域
typescript 复制代码
Text(this.poem.注释)
  .fontSize(16)
  .fontColor('#555555')
  .lineHeight(28)
  .width('100%')

注释区域使用稍小的字号和中灰色,与正文形成视觉层次。由于注释文本通常较长,使用 Scroll 容器包裹整个内容区域,确保内容过多时可以滚动查看。

六、路由配置

在 HarmonyOS 中,页面路由需要在 main_pages.json 中注册:

json 复制代码
{
  "src": [
    "pages/Index",
    "pages/PoemDetailPage"
  ]
}

列表中的顺序决定了页面在包中的索引顺序,首页必须排在第一位。当使用 router.pushUrl 跳转时,框架会根据这里注册的路径查找对应的页面文件进行加载。

这里有一个常见的坑:如果新增页面后忘记在 main_pages.json 中注册,运行时会报 "Cannot find page" 错误。所以每次新增页面文件时,一定要同步更新路由配置。

七、构建与打包

7.1 构建命令

HarmonyOS 项目使用 Hvigor 作为构建工具,类似于 Android 的 Gradle:

bash 复制代码
# 查看可用任务
hvigorw tasks

# 构建应用包(APP)
hvigorw assembleApp

# 仅构建模块包(HAP)
hvigorw assembleHap

7.2 构建产物

构建成功后,输出目录如下:

复制代码
build/outputs/default/
├── app6115-default-unsigned.app    # 未签名的应用包
├── pac.json                        # 包信息
└── pack.info                       # 包索引

entry/build/default/outputs/default/
├── entry-default-unsigned.hap      # 未签名的模块包
└── app/
    └── entry-default.hap           # 签了调试证书的 HAP(如有配置签名)

「HAP」(Harmony Ability Package)是 HarmonyOS 的应用模块包,类似于 Android 的 APK。一个「APP」包可以包含一个或多个 HAP 包。

7.3 签名配置

构建日志中有一行警告:

复制代码
Will skip sign 'hos_hap'. No signingConfigs profile is configured in current project.

这是因为项目没有配置签名信息。要在真机上运行,需要在 build-profile.json5 中配置签名。签名配置需要从华为开发者联盟获取证书和密钥。在 DevEco Studio 中,可以通过「File → Project Structure → Signing Configs」界面自动生成签名配置。

八、设计思路与用户体验

8.1 为什么要做古诗应用?

在信息爆炸的时代,人们的注意力被短视频、社交媒体不断切割。古诗词恰恰需要静下心来品味,一两分钟就能读完一首诗。这类轻量级的内容消费非常适合碎片化场景:等公交时、午休间隙、睡前片刻------打开应用读一首诗,既放松身心,又有所收获。

8.2 设计原则

  1. 内容优先:没有广告、没有复杂的交互,打开就是诗
  2. 沉浸阅读:米黄色背景模拟古籍纸张质感,减少眩光刺激
  3. 渐进学习:先看原文自行体会,再翻阅注释和译文对照理解
  4. 低门槛:无需登录、无网络依赖(数据内置),开箱即用

8.3 后续扩展方向

当前版本功能较为基础,后续可以从以下几个方面扩展:

  • 搜索功能:支持按诗名、作者、诗句关键词搜索
  • 收藏功能:用户可以将喜欢的诗加入收藏夹
  • 朗诵音频:为每首诗配上一段朗诵音频
  • 诗词接龙:小游戏化学习机制,提升用户粘性
  • 每日推荐:每天推送一首诗,培养阅读习惯
  • 多诗源:扩展至宋词、元曲等更多体裁
  • 深色模式:适配暗色主题,满足夜间阅读需求

九、踩坑与反思

9.1 问题一:ForEach 语法

在开发过程中遇到的第一个问题是 ForEach 的语法错误:

复制代码
ERROR: ',' expected. At File: Index.ets:87:7

排查后发现,ForEach 在 ArkTS 中不是普通的函数调用,而是编译期特殊处理的语法结构。它需要三个参数,即使不需要 keyGenerator,也必须为编译器提供明确的结构。最终通过添加 keyGenerator 参数并确保正确的括号嵌套解决了问题。

9.2 问题二:app.json5 label 校验

另一个问题出现在修改应用名称时:

复制代码
Schema validate failed: 'app.label' must match pattern
'^[$]string:[0-9a-zA-Z_.]+|(?=.*[{])(?=.*[}])[0-9a-zA-Z_.{}]+$'

原来 HarmonyOS 对 app.json5 中的 label 字段有严格的格式要求------它必须是资源引用(如 $string:app_name)或者包含模板占位符,不能直接写入中文文字。解决方案是将应用名称定义在 string.json 资源文件中,然后通过 $string:app_name 引用。

9.3 问题三:资源冲突警告

构建时出现了资源冲突警告:

复制代码
WARN: 'app_name' conflict, first declared at AppScope/.../string.json but declared again at entry/.../string.json

解决方法是在 entry 模块的 string.json 中移除与 AppScope 重复的 app_name 定义,避免资源覆盖冲突。

十、总结

通过「古诗小集」这个项目的开发,我们完整地走了一遍 HarmonyOS 应用开发的全流程:从项目初始化、数据建模、页面开发、路由配置到构建打包。整个应用代码量不到 400 行(包括数据),却实现了一个功能完整、界面优雅的古诗阅读器。

技术要点回顾

知识点 对应实现
Stage 模型 基于 UIAbility 的应用入口
ArkUI 声明式 UI Column / Row / List / Text 组件组合
ForEach 列表渲染 循环渲染古诗列表
页面路由 router.pushUrl + main_pages.json 注册
状态管理 @State + aboutToAppear 生命周期
资源管理 string.json / color.json / $r 引用
构建打包 hvigorw assembleApp

HarmonyOS 生态正在快速发展,ArkTS 和 ArkUI 的开发者体验也在不断提升。从我这个项目的实际体验来看,声明式 UI 的开发方式与 SwiftUI、Jetpack Compose 的思路非常接近,有相关经验的开发者可以很快上手。同时 HarmonyOS 对中文变量名、中文资源文件的良好支持,也体现了对本土开发者需求的深度理解。

古诗虽小,意境无穷。希望这款小应用能让更多人在忙碌的生活中,偶尔停下脚步,品味一首诗,感受千年前诗人笔下的月光与山河。


本文代码已在 HarmonyOS 6.1 SDK(API 23)环境下编译通过,构建产物为未签名的 APP 包,如需真机运行请自行配置签名证书。

相关推荐
全栈若城3 小时前
HarmonyOS AppUtil 应用配置控制:颜色模式/灰度/字体/语言/键盘避让详解
华为·harmonyos·arkts·harmonyos6·键盘避让·字体缩放
YOLO数据集集合3 小时前
无人机航拍街道巡检数据集 | 空中视角车辆检测、交通流量统计、违停识别、智能交通YOLO数据集10399期
深度学习·yolo·目标检测·无人机
放下华子我只抽RuiKe53 小时前
FastAPI 全栈后端(四):认证与授权
开发语言·前端·javascript·python·深度学习·react.js·fastapi
FrameNotWork3 小时前
HarmonyOS 6.1 Lottie动画集成完全指南:从踩坑到精通
华为·harmonyos
三声三视4 小时前
Electron 本地图片在鸿蒙 PC 上白图,我注册了个自定义协议
electron·harmonyos·鸿蒙
菜鸟‍4 小时前
【论文学习】Segment Anything 分割一切
深度学习·学习·计算机视觉
李二。4 小时前
日历日程管理工具 — 基于 HarmonyOS NEXT (API 23+) 的 ArkTS 纯声明式实现
华为·harmonyos
装不满的克莱因瓶4 小时前
自然语言处理发展历史——从规则系统到大语言模型的演进之路
网络·人工智能·python·深度学习·语言模型·自然语言处理
金启攻4 小时前
鸿蒙原生应用实战(三):搜索与详情页 —— 多维度筛选与动态路由
华为·harmonyos