【鸿蒙原生开发实战】第五篇:主题切换与发布准备——深色模式、设置页面、签名与构建
本文是鸿蒙原生开发实战系列的第五篇,主要介绍如何为「知墨」笔记应用完善发布前的关键功能。内容包含: 深色/浅色主题切换实现方案 系统级主题设置 颜色资源文件配置 全局状态管理 提供了详细的color.json资源文件示例 设置页面开发 包含外观设置、数据管理和关于页面 实现主题切换开关 添加示例数据功能 数据重置操作 发布准备 涵盖签名与构建流程 生成可发布的HAP包 文章详细讲解了主题切换的架构
【鸿蒙原生开发实战】第五篇:主题切换与发布准备——深色模式、设置页面、签名与构建
前言
经过前面四篇的开发,「知墨」笔记应用的核心功能已经完备。但一个完整的应用还需要:
- 深色/浅色主题切换——提升用户体验
- 设置页面——整合数据管理功能
- Seed 数据——方便初次体验
- 构建与签名——生成可发布的 HAP 包
本篇是系列的收官之作,我们将完成以上所有内容,把一个开发中的项目变成可交付的应用。
一、深色/浅色主题切换
1.1 主题架构设计
主题切换涉及三个层面:
| 层面 | 实现方式 | 影响范围 |
|---|---|---|
| 系统级 | setColorMode() |
系统控件(状态栏、对话框) |
| 颜色资源 | $r('app.color.xxx') |
所有引用了颜色资源的 UI 组件 |
| 自定义状态 | AppStorage 传递 theme 标志 |
业务组件的条件渲染 |
1.2 ThemeService 实现
前面第二篇已经介绍了 ThemeService 的初始化部分,这里聚焦切换逻辑:
async toggle(): Promise<boolean> {
await this.setDarkMode(!this.isDark);
return this.isDark;
}
private applyTheme(): void {
AppStorage.setOrCreate('isDarkTheme', this.isDark);
try {
const ctx = AppStorage.get<Context>('appContext');
if (ctx) {
ctx.getApplicationContext().setColorMode(
this.isDark
? ConfigurationConstant.ColorMode.COLOR_MODE_DARK
: ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT,
);
}
} catch (e) { /* ignore */ }
}
关键点:
setColorMode()是 ApplicationContext 的 API,必须通过应用级 Context 调用AppStorage.setOrCreate('isDarkTheme', this.isDark)将主题状态存入全局存储- 后续其他组件可以通过
@StorageProp('isDarkTheme')监听主题变化
1.3 颜色资源文件
在 entry/src/main/resources/base/element/color.json 中定义了主题色板:
{
"color": [
{ "name": "background", "value": "#FFF5F5F5" },
{ "name": "surface", "value": "#FFFFFFFF" },
{ "name": "surface_variant", "value": "#FFF0F0F3" },
{ "name": "primary", "value": "#FF6C5CE7" },
{ "name": "text_primary", "value": "#FF1A1A2E" },
{ "name": "text_secondary", "value": "#FF6C6C80" },
{ "name": "border", "value": "#FFE8E8EE" },
{ "name": "shadow", "value": "#0A000000" },
{ "name": "danger", "value": "#FFE17055" }
]
}
这是浅色主题的颜色定义。深色主题需要在 resources/dark/element/color.json 中覆盖:
{
"color": [
{ "name": "background", "value": "#FF0D0D1A" },
{ "name": "surface", "value": "#FF1A1A2E" },
{ "name": "surface_variant", "value": "#FF252540" },
{ "name": "primary", "value": "#FF8B7CFA" },
{ "name": "text_primary", "value": "#FFEEEEF0" },
{ "name": "text_secondary", "value": "#FF9E9EB0" },
{ "name": "border", "value": "#FF2E2E45" },
{ "name": "shadow", "value": "#30000000" },
{ "name": "danger", "value": "#FFE17055" }
]
}
HarmonyOS 资源覆盖机制:系统会自动根据 setColorMode() 设置的主题加载对应 dark/ 或 base/ 目录下的资源,开发者只需要在 color.json 中定义好两套颜色,组件中用 $r('app.color.background') 引用即可。
二、SettingsPage 设置页面
2.1 页面组成
设置页面包含三个分组:
设置
├── 外观
│ ├── 深色模式 → [Switch 开关]
│ └── 笔记数量 → "共 X 篇笔记"
├── 数据管理
│ ├── [添加示例笔记] 按钮
│ └── [重置所有数据] 按钮
└── 关于
├── 应用名称 → 知墨
├── 版本 → 1.0.0
└── 技术栈 → ArkTS + Preferences
2.2 深色模式开关
Row() {
Column({ space: 4 }) {
Text('深色模式').fontSize(15)
Text('切换浅色/深色主题').fontSize(12)
.fontColor($r('app.color.text_secondary'))
}
.layoutWeight(1)
Toggle({ type: ToggleType.Switch, isOn: this.isDark })
.onChange(() => { this.onToggleTheme(); })
}
ArkUI 的 Toggle({ type: ToggleType.Switch }) 提供了标准的 Switch 组件。isOn 参数控制开关状态。
2.3 示例数据填充
为了让用户第一次打开应用时有内容可看,SettingsPage 内置了 5 条示例笔记:
async onAddSampleData(): Promise<void> {
const samples: string[][] = [
['HarmonyOS 开发入门', 'HarmonyOS 是华为开发的分布式操作系统...', 'tech', 'HarmonyOS,ArkTS'],
['周末爬山计划', '周六早上8点出发,带上水和干粮...', 'life', '运动,周末'],
['项目周报模板', '1. 本周完成事项\n2. 遇到的问题...', 'work', '工作,模板'],
['设计模式笔记:观察者模式', '观察者模式定义了对象之间的一对多依赖...', 'study', '设计模式,编程'],
['App 新功能构思', '1. 数据导出为 Markdown\n2. 笔记分享...', 'idea', '产品,功能'],
];
for (const s of samples) {
const tagList = s[3].split(',').map(t => t.trim());
await noteUseCases.addNote(s[0], s[1], s[2], tagList);
}
await this.loadStats();
}
每条笔记覆盖了不同的分类(技术、生活、工作、学习、灵感),方便测试分类筛选功能。
2.4 数据重置
async onResetData(): Promise<void> {
AlertDialog.show({
title: '重置数据',
message: `确定要清除全部 ${this.noteCount} 篇笔记吗?此操作不可撤销。`,
primaryButton: { value: '取消', action: () => {} },
secondaryButton: {
value: '清除',
action: async () => {
const allNotes = await noteUseCases.getAllNotes();
for (const note of allNotes) {
await noteUseCases.deleteNote(note.id);
}
await noteUseCases.reload();
await this.loadStats();
}
}
});
}
设计考虑:noteCount 动态显示当前笔记数量,让用户清楚重置会丢失多少数据。危险的"清除"按钮用红色($r('app.color.danger'))高亮警示。
三、color.json 完整配置
为了让主题切换生效,需要确保 entry/src/main/resources/ 目录下有以下结构:
resources/
├── base/
│ ├── element/
│ │ ├── color.json # 浅色主题颜色
│ │ ├── string.json # 字符串资源
│ │ └── boolean.json # 布尔资源
│ ├── media/ # 图片资源
│ └── profile/
│ └── main_pages.json # 页面路由注册
├── dark/
│ └── element/
│ └── color.json # 深色主题颜色覆盖
├── en_US/ # 英文资源(可选)
└── zh_CN/ # 中文资源
四、构建 Release 包与签名
4.1 生成签名文件
在 DevEco Studio 中生成签名证书的步骤:
-
打开 Build → Generate Key and CSR
-
填写证书信息:
- Alias: knowink_key
- Validity: 25 years
- Key Algorithm: RSA 2048
-
生成的
.p12文件和.csr文件保存在项目sign/目录下
4.2 配置签名
在 build-profile.json5 中添加签名配置:
{
"app": {
"signingConfigs": [
{
"name": "default",
"material": {
"storeFile": "./sign/knowink.p12",
"storePassword": "your_password",
"keyAlias": "knowink_key",
"keyPassword": "your_password",
"profileFile": "./sign/knowink_release.p7b",
"certpath": "./sign/knowink_release.cer"
}
}
],
// ...
}
}
注意:实际密码不要明文提交到 Git。可以使用环境变量或
.gitignore排除签名文件。我们项目中已经配置了signingConfigs: [](空数组),请按需添加。
4.3 构建 HAP 包
# Debug 构建
hvigorw assembleHap --mode debug
# Release 构建(需要配置签名)
hvigorw assembleHap --mode release
构建产物位于:
entry/build/default/outputs/
├── default/
│ ├── entry-default-debug.hap # Debug 包
│ └── entry-default-signed.hap # 签名包(Release)
└── entry-default-unsigned.hap # 未签名包
五、项目文件总览
至此,「知墨」笔记应用共包含 17 个源文件:
| 层 | 文件 | 行数(约) | 职责 |
|---|---|---|---|
| Domain | models/Note.ts |
32 | 笔记实体定义 |
models/Category.ts |
22 | 分类定义 | |
usecases/NoteUseCases.ts |
52 | 业务用例编排 | |
| Data | repositories/NoteRepository.ts |
148 | 数据持久化仓库 |
services/PreferencesService.ts |
40 | Preferences 封装 | |
services/ThemeService.ts |
49 | 主题管理 | |
| UI | core/NoteCard.ets |
90 | 笔记卡片组件 |
core/StatsCard.ets |
30 | 统计卡片组件 | |
core/EmptyState.ets |
25 | 空状态占位组件 | |
core/CategoryBadge.ets |
22 | 分类徽章组件 | |
| Pages | Index.ets |
228 | 主页面 |
NoteDetailPage.ets |
199 | 笔记详情页 | |
NoteEditPage.ets |
184 | 新建/编辑页 | |
SearchPage.ets |
117 | 搜索页 | |
SettingsPage.ets |
199 | 设置页 | |
| Entry | EntryAbility.ets |
48 | Ability 入口 |
EntryBackupAbility.ets |
- | 备份 Ability |
总代码量:约 1500 行 ArkTS 代码,实现了完整的笔记 CRUD、分类管理、搜索、主题切换等功能。
六、开发心得与避坑指南
6.1 构建踩坑回顾
| 问题 | 原因 | 解决方案 |
|---|---|---|
DEVECO_SDK_HOME Invalid |
daemon 缓存旧环境变量 | --stop-daemon 后重试 |
build-profile.json5 not found |
在错误目录执行 hvigorw | cd 到项目根目录 |
| EPERM mkdir | 在工具目录下执行构建 | 在项目目录执行 |
| Preferences 数据丢失 | 未调 flush() |
put 后显式调用 flush |
6.2 后续可扩展方向
「知墨」目前是一个单机笔记应用,如果需要继续迭代,可以考虑:
- 数据云同步:基于华为云(AGConnect)的云数据库,实现多设备同步
- 富文本编辑:支持 Markdown 渲染
- 图片附件:使用
@kit.MediaLibraryKit访问相册 - Widget 卡片:在桌面上展示最近笔记
- 语音输入:基于
@kit.VoiceCallKit的语音转文字 - 分布式协同:利用 HarmonyOS 分布式数据管理在多设备间流转


七、系列总结
五篇博文路线图
第一篇:环境搭建与项目初始化
↓ DevEco Studio 安装、SDK 配置、hvigor 构建、项目结构
第二篇:数据层与核心架构
↓ Clean Architecture、领域模型、Repository、Preferences
第三篇:UI组件与主页开发
↓ CategoryBadge/StatsCard/NoteCard/EmptyState、主页面
第四篇:多页面路由与交互
↓ 详情页、编辑页、搜索页、路由机制、表单校验
第五篇:主题切换与发布准备
↓ 深色模式、设置页、签名、构建 HAP、项目总结
学习收获
通过「知墨」笔记应用的完整开发,我们实践了:
- ✅ ArkTS 语言:interface、class、async/await、装饰器语法
- ✅ ArkUI 声明式框架:@Component、@State、@Prop、build() 链式调用
- ✅ 页面路由:router.pushUrl/back/getParams、页面注册
- ✅ 数据持久化:Preferences API、JSON 序列化
- ✅ 组件化设计:自定义组件拆分、Props 传递、回调函数
- ✅ 主题管理:AppStorage、setColorMode、资源覆盖机制
- ✅ 构建发布:hvigorw、签名配置、HAP 打包
开发环境:DevEco Studio 6.1 | HarmonyOS SDK 6.1.0 (API 23) | ArkTS + ArkUI
如果你对这个项目有任何问题或建议,欢迎在评论区讨论!
更多推荐



所有评论(0)