鸿蒙ArkTS原生体重记录 - 数据可视化图表 体重追踪工具

概述
体重记录应用是 HarmonyOS 应用生态中的一个典型健康追踪类应用。本文基于 entry/src/main/ets/pages/life/WeightRecord.ets 的实现,深入剖析该应用的技术架构、核心数据结构和关键算法实现。该应用实现了体重数据的记录、存储、统计展示以及 BMI 健康指标计算等功能,采用 HarmonyOS 官方推荐的 ArkUI 声明式开发范式,充分利用了 @State 状态管理、Grid 网格布局、Slider 滑块组件等原生能力。
应用的核心技术特点包括:使用 TypeScript interface 静态类型系统定义数据结构,确保代码的类型安全;采用 Slider 组件实现直观的体重数值输入;通过 Grid 网格布局展示多维度统计数据;实现 BMI 计算算法并根据体质分类动态调整颜色提示。整个应用遵循模块化设计原则,数据存储、业务逻辑和 UI 渲染层分离,便于维护和扩展。
1. 技术架构分析
1.1 整体架构设计
体重记录应用采用经典的三层架构模式,将界面展示层、业务逻辑层和数据持久层进行了清晰分离。这种分层设计遵循了 HarmonyOS 应用开发的设计原则,使得各层职责明确,耦合度低,便于独立开发和测试。
┌─────────────────────────────────────────────────────────────┐
│ UI 展示层 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ CommonTitleBar │ │ Slider输入 │ │ Grid统计 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ 业务逻辑层 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ app_addRecord │ │ app_deleteRecord │ │ app_getStats │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ app_getBMI │ │ app_getBMICategory │ │
│ └─────────────┘ └─────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ 数据持久层 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ AppStorage 工具类 │ │
│ │ app_setString / app_getString / app_setNumber │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
UI 展示层完全基于 ArkUI 声明式范式构建,所有界面元素都通过 @Component 装饰器标注的组件结构声明。组件内部使用 @State 装饰器管理可变状态,当状态变化时,框架自动触发 UI 重新渲染。业务逻辑层封装在组件的方法中,包括记录的增删改查、统计数据的计算、BMI 的算法实现等。数据持久化则通过 AppStorage 工具类封装 preferences API 完成,提供同步的 get 操作和异步的 put 操作。
1.2 模块依赖关系
应用的主要依赖关系清晰明了。WeightRecord 组件直接依赖 CommonTitleBar 通用标题栏组件和 AppStorage 存储工具类。CommonTitleBar 进一步依赖 AppRouter 路由工具实现页面导航。这种依赖结构符合单向依赖原则,避免了循环依赖问题。
WeightRecord.ets
├── CommonTitleBar.ets
│ └── router.ets (AppRouter)
└── storage.ets (AppStorage)
└── @ohos.data.preferences
值得注意的是,AppStorage 底层使用了 HarmonyOS 提供的 dataPreferences 模块,这是官方推荐的应用本地数据存储方案。相比于直接使用文件操作,preferences API 提供了更高级的键值对存储抽象,自动处理序列化反序列化,API 更加简洁易用。
1.3 状态管理机制
应用采用 HarmonyOS 原生的响应式状态管理机制。组件级别的状态通过 @State 装饰器声明,这些状态变量具有以下特性:私有性(只能在组件内部访问)、响应性(值变化会触发 UI 更新)、可变性和继承性(子组件可以通过父组件传递参数获取状态)。
@State app_records: App_WeightRecord[] = []; // 体重记录列表
@State app_currentWeight: number = 60; // 当前输入体重值
@State app_note: string = ''; // 备注信息
@State app_targetWeight: number = 55; // 目标体重
@State app_minWeight: number = 30; // 体重范围下限
@State app_maxWeight: number = 150; // 体重范围上限
当用户操作 Slider 改变 app_currentWeight 值时,框架检测到状态变化,自动重新执行组件的 build 方法,UI 中所有引用该状态变量的地方都会反映最新值。这种声明式状态管理大大简化了 UI 更新逻辑,开发者无需手动操作 DOM 或调用渲染方法,只需关注状态变化本身。
2. 核心数据结构
2.1 体重记录接口定义
应用使用 TypeScript interface 静态类型定义了体重记录的数据结构,这是 ArkTS 静态类型检查的基础。
interface App_WeightRecord {
app_date: string;
app_weight: number;
app_note: string;
}
该接口包含三个字段:app_date 为字符串类型,记录体重数据的日期,格式为本地化的中文日期字符串(如 “2026/6/17”);app_weight 为 number 类型,记录体重数值,单位为千克;app_note 为字符串类型,可选的备注信息,用于用户记录当天的特殊状况如饮食、运动等。
采用 interface 定义数据结构有多方面优势。首先,静态类型检查可以在编译阶段发现类型错误,避免运行时类型异常。其次,明确的字段定义提供了自文档化效果,代码可读性高。再次,IDE 可以基于类型提供智能补全和类型检查提示,提升开发效率。在 ArkTS 中,interface 被编译成 ArkUI 框架内部的高效数据结构,兼顾类型安全和运行时性能。
2.2 数据结构与 JSON 序列化
体重记录列表在存储时需要序列化 为 JSON 字符串。应用使用 JSON.parse() 和 JSON.stringify() 完成双向转换。
// 从存储加载记录
const app_storedRecords: string = app_getString('weight_records', '[]');
try {
this.app_records = JSON.parse(app_storedRecords);
} catch (error) {
this.app_records = [];
}
// 保存记录到存储
app_setString('weight_records', JSON.stringify(this.app_records));
这里使用了 try-catch 包裹 JSON.parse 操作,以防存储数据损坏导致解析失败。解析失败时采用防御性编程策略,将记录列表置为空数组,确保应用不会因数据异常而崩溃。默认值 '[]' 使用空 JSON 数组字符串,这样即使存储键不存在,也能保证 parse 操作成功。
3. 核心代码模块详解
3.1 数据管理模块
数据管理模块负责体重记录的增删改查操作,是应用业务逻辑的核心部分。该模块实现了三个主要方法:app_addRecord 用于添加新记录、app_deleteRecord 用于删除历史记录、app_saveRecords 用于持久化存储。
3.1.1 添加记录功能
app_addRecord(): void {
const app_newRecord: App_WeightRecord = {
app_date: new Date().toLocaleDateString('zh-CN'),
app_weight: this.app_currentWeight,
app_note: this.app_note.trim()
};
this.app_records.unshift(app_newRecord);
this.app_note = '';
this.app_saveRecords();
}
添加记录方法的实现逻辑清晰。首先构建一个新的记录对象,日期使用 toLocaleDateString('zh-CN') 获取本地化格式的中文日期。体重值直接取自当前输入状态 app_currentWeight,这是用户通过 Slider 输入的数值。备注信息使用 trim() 方法去除首尾空白字符,防止无效空白数据存入列表。
新记录通过 unshift() 方法插入到数组开头,这保证了最新记录总是出现在列表最前面,符合时间线展示的直觉。添加完成后,清空备注输入框,为下次输入做准备。最后调用 app_saveRecords() 将更新后的完整列表同步到持久化存储。
3.1.2 删除记录功能
app_deleteRecord(app_index: number): void {
this.app_records.splice(app_index, 1);
this.app_saveRecords();
}
删除记录使用数组的 splice() 方法,从指定索引位置删除一个元素。参数 app_index 对应 ForEach 遍历时的索引值。由于列表采用 unshift() 方式添加,最新记录索引为 0,越早的记录索引越大,这与用户查看列表的顺序完全对应。
删除操作后立即调用 app_saveRecords() 同步存储,确保数据一致性。这里没有做数组越界检查,因为 ForEach 的索引范围天然被数组长度限制,但在生产环境中建议增加防御性检查。
3.1.3 存储抽象层
app_saveRecords(): void {
app_setString('weight_records', JSON.stringify(this.app_records));
}
存储操作通过 AppStorage 工具类完成,该类封装了 preferences API 的复杂操作。app_setString() 方法接受键名和字符串值,将数据异步写入本地存储。相比于直接调用 preferences API,AppStorage 提供了同步的 get 操作和简化的 put 接口,错误处理也更友好。
3.2 统计计算模块
统计计算模块提供数据分析和指标计算功能,是体重记录应用的核心算法部分。该模块包含 app_getStats() 统计方法以及 BMI 相关的三个辅助方法。
3.2.1 统计方法实现
app_getStats(): { app_current: number; app_avg: number; app_max: number; app_min: number; app_diff: number } {
if (this.app_records.length === 0) {
return { app_current: 0, app_avg: 0, app_max: 0, app_min: 0, app_diff: 0 };
}
const app_weights: number[] = this.app_records.map((app_r: App_WeightRecord) => app_r.app_weight);
const app_current: number = app_weights[0];
const app_avg: number = parseFloat((app_weights.reduce((a: number, b: number) => a + b, 0) / app_weights.length).toFixed(1));
const app_max: number = Math.max(...app_weights);
const app_min: number = Math.min(...app_weights);
const app_diff: number = parseFloat((app_current - this.app_targetWeight).toFixed(1));
return { app_current, app_avg, app_max, app_min, app_diff };
}
统计方法首先处理空列表的边界情况,返回全零对象避免后续计算错误。然后使用 map() 提取所有体重值生成新数组,这是函数式编程的典型用法,代码简洁且表达意图清晰。
当前体重取数组第一个元素,即最新录入的体重值。平均值通过 reduce() 累加求和后除以元素个数,再使用 toFixed(1) 保留一位小数,最后 parseFloat() 转回数值类型。最大值和最小值分别使用 Math.max() 和 Math.min() 的展开语法计算。距离目标的差值用当前体重减去目标体重,正值表示超过目标,负值表示低于目标。
返回值为内联声明的对象类型,明确了五个统计指标的组成。这种写法省去了额外定义接口的步骤,代码更紧凑,适合内部使用的临时数据结构。
3.2.2 BMI 计算方法
app_getBMI(app_weight: number): number {
const app_height: number = 1.7;
return parseFloat((app_weight / (app_height * app_height)).toFixed(1));
}
BMI(Body Mass Index,身体质量指数)是衡量人体肥胖程度的国际通用指标。计算公式为体重(千克)除以身高(米)的平方。方法中硬编码身高为 1.7 米,这是一个简化处理,实际应用中应该允许用户设置个人身高数据。返回值同样保留一位小数,保持数据精度一致性。
3.2.3 BMI 分类方法
app_getBMICategory(app_bmi: number): string {
if (app_bmi < 18.5) return '偏瘦';
if (app_bmi < 24) return '正常';
if (app_bmi < 28) return '偏胖';
return '肥胖';
}
BMI 分类采用中国成人标准,这是根据中国国情调整后的分类体系:
| BMI 范围 | 分类 | 说明 |
|---|---|---|
| < 18.5 | 偏瘦 | 体重过低,可能存在营养不良风险 |
| 18.5 ~ 24 | 正常 | 健康体重范围 |
| 24 ~ 28 | 偏胖 | 超重,需要关注饮食和运动 |
| >= 28 | 肥胖 | 肥胖标准,建议咨询医生 |
3.2.4 BMI 颜色映射方法
app_getBMIColor(app_bmi: number): string {
if (app_bmi < 18.5) return '#52C41A';
if (app_bmi < 24) return '#007DFF';
if (app_bmi < 28) return '#FAAD14';
return '#FF4D4F';
}
BMI 颜色方法返回十六进制颜色代码,与 UI 设计系统的颜色定义保持一致:
| BMI 分类 | 颜色代码 | 颜色名称 | 语义 |
|---|---|---|---|
| 偏瘦 | #52C41A | 绿色 | 提示用户注意营养摄入 |
| 正常 | #007DFF | 蓝色 | 表示健康状态 |
| 偏胖 | #FAAD14 | 黄色 | 警告用户注意体重管理 |
| 肥胖 | #FF4D4F | 红色 | 强烈建议采取行动 |
颜色语义符合直觉心理学原理:绿色代表正常通行,蓝色给人安心感觉,黄色提醒注意,红色警示危险。用户扫一眼颜色就能快速判断当前体重状态,无需阅读具体数值。
3.3 UI 组件模块
UI 组件模块是应用的可视化层,完全采用 ArkUI 声明式范式构建。所有 UI 元素都作为组件树的节点声明,数据驱动渲染,开发者无需手动操作视图更新。
3.3.1 标题栏组件
CommonTitleBar({
app_title: '体重记录',
app_showBack: true
})
标题栏是应用的通用导航组件,传入标题文本和返回按钮显示标志两个参数。组件内部实现包含返回按钮、图片资源和标题文本的布局,返回按钮点击时调用 AppRouter.app_back() 返回上一页面。这种通用组件抽取避免了代码重复,提升了项目的一致性和可维护性。
3.3.2 Slider 体重输入组件
Slider({
value: this.app_currentWeight,
min: this.app_minWeight,
max: this.app_maxWeight,
step: 0.1
})
.blockColor($r('app.color.app_color_primary'))
.trackColor('#E5E5E5')
.selectedColor($r('app.color.app_color_primary'))
Slider 是 HarmonyOS 提供的原生滑块组件,非常适合体重这类连续数值的选择场景。核心配置参数说明:
| 参数 | 值 | 说明 |
|---|---|---|
| value | app_currentWeight | 绑定状态变量,双向同步 |
| min | 30 | 体重下限,单位 kg |
| max | 150 | 体重上限,单位 kg |
| step | 0.1 | 步进值,支持精确到小数 |
样式配置中,blockColor 设置滑块颜色,trackColor 设置轨道默认颜色,selectedColor 设置已选择部分的轨道颜色。通过 $r('app.color.app_color_primary') 引用应用主题色,保持视觉一致性。Slider 组件的 onChange 事件在用户拖动时触发(ARKUI具体行为),默认情况下状态变量会自动更新,无需额外处理。
3.3.3 Grid 统计网格组件
Grid() {
GridItem() {
Column({ space: 8 }) {
Text('当前')
.fontSize(14)
.fontColor($r('app.color.app_color_text_secondary'))
Text(`${this.app_getStats().app_current} kg`)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor($r('app.color.app_color_text_primary'))
}
// ... 样式配置
}
// ... 其他 GridItem
}
.columnsTemplate('1fr 1fr')
.columnsGap(8)
.rowsGap(8)
.width('100%')
Grid 网格布局组件用于以网格形式展示统计数据。通过 columnsTemplate('1fr 1fr') 设置两列等宽布局,columnsGap 和 rowsGap 分别设置列间距和行间距。GridItem 作为 Grid 的子元素,每个代表一个统计卡片。
四个统计卡片分别展示当前体重、平均体重、距离目标差值和 BMI 指数。前三个卡片的内容通过 app_getStats() 方法获取,BMI 卡片额外使用 app_getBMIColor() 动态设置颜色。距离目标差值根据正负情况使用不同颜色:超过目标显示危险色,低于或达到目标显示成功色。
Grid 布局的优势在于自动处理行列排列,添加或删除数据时无需调整布局代码,框架会自动计算网格尺寸。这比使用 Row 和 Column 嵌套实现网格更加简洁且易于维护。
3.3.4 历史记录列表组件
Scroll() {
Column({ space: 8 }) {
ForEach(this.app_records, (app_record: App_WeightRecord, app_index: number) => {
Row({ space: 12 }) {
Column({ space: 4 }) {
Text(app_record.app_date)
.fontSize(14)
.fontColor($r('app.color.app_color_text_secondary'))
if (app_record.app_note) {
Text(app_record.app_note)
.fontSize(12)
.fontColor($r('app.color.app_color_text_tertiary'))
}
}
.width('flexGrow')
Text(`${app_record.app_weight} kg`)
.fontSize(16)
.fontWeight(FontWeight.Medium)
.fontColor($r('app.color.app_color_text_primary'))
Button('删除')
.onClick(() => this.app_deleteRecord(app_index))
}
// ... 样式配置
})
}
.width('100%')
}
.width('100%')
.height(200)
历史记录列表使用 Scroll 滚动容器包裹 ForEach 循环渲染的记录项。Scroll 提供了垂直滚动能力,当记录数量超过显示区域时可以滚动查看。ForEach 是 ArkUI 的列表渲染语法,第一个参数是数据源数组,第二个参数是渲染回调函数,接收单个数据项和索引。
每个记录项布局采用水平 Row 容器,左侧是日期和备注信息(使用 Column 实现垂直排列),中间是体重数值,右侧是删除按钮。备注信息使用 if 条件渲染,只有存在备注内容时才显示,避免空行影响布局美观。删除按钮通过 onClick 事件绑定删除方法,传入当前记录的索引值。
高度固定为 200vp,这是一个经验值,兼顾了显示效率和屏幕空间利用。如果记录数量少,剩余空间会留白;如果记录多,滚动查看是合理的用户体验设计。
3.5 生命周期管理模块
HarmonyOS 应用组件具有完整的生命周期钩子,WeightRecord 组件使用了 aboutToAppear 和 aboutToDisappear 两个最重要的生命周期回调。
3.5.1 组件即将显示时
aboutToAppear(): void {
const app_storedRecords: string = app_getString('weight_records', '[]');
try {
this.app_records = JSON.parse(app_storedRecords);
} catch (error) {
this.app_records = [];
}
this.app_targetWeight = app_getNumber('weight_target', 55);
if (this.app_records.length > 0) {
this.app_currentWeight = this.app_records[0].app_weight;
}
}
aboutToAppear 在组件即将显示前调用,是初始化数据的好时机。方法中完成三项初始化工作:首先从持久化存储加载体重记录列表,使用 try-catch 处理可能的 JSON 解析异常;然后加载用户之前设置的目标体重,如果不存在则使用默认值 55kg;最后,如果有历史记录,将当前输入体重初始化为最新一条记录的体重值,方便用户在此基础上微调录入新数据。
3.5.2 组件即将销毁时
aboutToDisappear(): void {
app_setString('weight_records', JSON.stringify(this.app_records));
app_setNumber('weight_target', this.app_targetWeight);
}
aboutToDisappear 在组件即将销毁前调用,是保存数据的关键时机。方法将当前记录列表和目标体重同步到持久化存储。由于 preferences 的 put 操作是异步的,这里直接调用 app_setString 和 app_setNumber,它们内部会处理异步写入,组件销毁不会等待写入完成。这种设计在大多数场景下是安全的,但如果应用在写入完成前被强制终止,可能导致数据丢失。更严格的场景可以使用 aboutToDisappear 返回 Promise 并等待完成。
4. 数据持久化机制
4.1 AppStorage 工具类设计
AppStorage 是应用级别的数据存储抽象层,封装了 HarmonyOS 的 preferences API,提供简洁统一的存储接口。
export class AppStorage {
static async app_setString(app_key: string, app_value: string): Promise<void> {
if (app_pref_instance !== null) {
try {
await app_pref_instance.putSync(app_key, app_value);
await app_pref_instance.flushSync();
} catch (error) {
console.error(`存储设置失败: ${error}`);
}
}
}
static app_getString(app_key: string, app_defaultValue: string): string {
if (app_pref_instance !== null) {
try {
return app_pref_instance.getSync(app_key, app_defaultValue) as string;
} catch (error) {
console.error(`存储获取失败: ${error}`);
return app_defaultValue;
}
}
return app_defaultValue;
}
// ... 其他方法类似
}
该工具类的设计有几个值得注意的点。set 操作设计为异步方法(async),内部使用 putSync 配合 flushSync 确保数据写入底层存储。get 操作设计为同步方法,直接返回结果,使用更方便。两种操作都包含完善的异常处理,失败时记录日志并返回默认值。类型参数使用泛型约束,返回值通过类型断言转换,确保类型安全。
4.2 存储数据结构
应用使用两个存储键管理数据:
| 存储键 | 数据类型 | 说明 |
|---|---|---|
| weight_records | JSON字符串 | App_WeightRecord[] 数组序列化 |
| weight_target | number | 用户目标体重,单位 kg |
这种简单的键值对存储适合小规模数据场景。weight_records 作为 JSON 数组字符串存储,支持任意数量的记录,每条记录包含日期、体重和备注三个字段。weight_target 作为单独的数字值存储,允许用户独立调整目标体重而不影响记录数据。
5. BMI 算法与健康指标体系
5.1 BMI 算法原理
BMI(Body Mass Index,身体质量指数)是目前国际通用的衡量人体胖瘦程度以及是否健康的指标。计算公式简单直观:
BMI = 体重(kg) ÷ 身高(m)²
以体重 65kg、身高 1.7m 为例:
BMI = 65 ÷ (1.7 × 1.7) = 65 ÷ 2.89 ≈ 22.5
方法实现代码:
app_getBMI(app_weight: number): number {
const app_height: number = 1.7;
return parseFloat((app_weight / (app_height * app_height)).toFixed(1));
}
5.2 BMI 分类标准
应用采用中国成人 BMI 分类标准,这是《中国居民膳食指南》推荐的标准:
┌────────────────────────────────────────────────────────────┐
│ BMI 分类对照表 │
├─────────────┬──────────────┬──────────────────────────────┤
│ BMI范围 │ 分类 │ 建议 │
├─────────────┼──────────────┼──────────────────────────────┤
│ < 18.5 │ 偏瘦 │ 注意营养均衡,增加蛋白质摄入 │
│ 18.5~24 │ 正常 │ 保持现有生活方式 │
│ 24~28 │ 偏胖 │ 控制饮食,适量增加运动 │
│ ≥ 28 │ 肥胖 │ 建议咨询医生,制定减重计划 │
└─────────────┴──────────────┴──────────────────────────────┘
5.3 颜色语义设计
BMI 颜色映射是典型的语义化颜色设计案例:
app_getBMIColor(app_bmi: number): string {
if (app_bmi < 18.5) return '#52C41A'; // 绿色 - 通行/正常
if (app_bmi < 24) return '#007DFF'; // 蓝色 - 安全/可信
if (app_bmi < 28) return '#FAAD14'; // 黄色 - 警告/注意
return '#FF4D4F'; // 红色 - 危险/紧急
}
这种颜色梯度设计遵循色彩心理学的直觉联想原则,用户无需阅读文字就能感知健康状态。实际应用中,绿色和蓝色属于安全色系,黄色属于警示色系,红色属于禁止/危险色系。颜色与应用主题色 #007DFF(蓝色)保持一致,只有在异常状态时才使用其他颜色,形成了良好的视觉层次。
6. 页面布局结构分析
6.1 整体布局架构
页面采用垂直布局(Column),从头到尾依次排列各个功能区块:
Column (根容器)
├── CommonTitleBar (标题栏,高度56)
├── Column (内容区,flexGrow)
│ ├── Column (体重输入区)
│ │ ├── Text ('当前体重')
│ │ ├── Row (数值展示)
│ │ ├── Slider (体重滑块)
│ │ ├── TextField (备注输入)
│ │ └── Button ('记录')
│ ├── Column (目标体重区)
│ │ ├── Text ('目标体重')
│ │ └── Row (Slider + 数值)
│ ├── Column (统计区,条件渲染)
│ │ ├── Text ('统计数据')
│ │ └── Grid (2x2 网格)
│ └── Column (历史记录区,条件渲染)
│ ├── Text ('历史记录')
│ └── Scroll + ForEach (列表)
这种自上而下的线性布局符合移动端用户的阅读习惯,重要信息(体重输入)放在最上方便于操作,次要信息(历史记录)放在下方可以通过滚动查看。
6.2 条件渲染策略
统计区和历史记录区使用 if 条件渲染,只有当存在记录时才显示:
if (this.app_records.length > 0) {
Column({ space: 12 }) {
// 统计区内容
}
Column({ space: 12 }) {
// 历史记录区内容
}
}
这种设计有两个好处:空状态下页面更简洁,不会显示空洞的统计卡片或空列表提示;避免在无数据时计算统计值,减少不必要的计算开销。条件渲染是 ArkUI 声明式范式的核心特性,状态驱动渲染,代码比传统的 show/hide 模式更简洁。
6.3 响应式设计考虑
布局中使用了一些响应式设计的技巧:
- 宽度统一使用
'100%',自适应屏幕宽度 - 内边距使用固定值(16vp),保持内容与边缘的安全距离
- Grid 使用
1fr 1fr等分列,自适应不同屏幕宽度 - 高度使用固定值或内容自适应,避免溢出
这些设计使得应用能够适配不同尺寸的 HarmonyOS 设备,从手机到平板都有合理的显示效果。
7. 关键代码片段速查
7.1 数据结构定义
interface App_WeightRecord {
app_date: string;
app_weight: number;
app_note: string;
}
7.2 状态变量声明
@State app_records: App_WeightRecord[] = [];
@State app_currentWeight: number = 60;
@State app_note: string = '';
@State app_targetWeight: number = 55;
@State app_minWeight: number = 30;
@State app_maxWeight: number = 150;
7.3 Slider 组件配置
Slider({
value: this.app_currentWeight,
min: this.app_minWeight,
max: this.app_maxWeight,
step: 0.1
})
.blockColor($r('app.color.app_color_primary'))
.trackColor('#E5E5E5')
.selectedColor($r('app.color.app_color_primary'))
7.4 Grid 布局配置
Grid() {
// GridItem 元素
}
.columnsTemplate('1fr 1fr')
.columnsGap(8)
.rowsGap(8)
.width('100%')
7.5 BMI 计算与分类
app_getBMI(app_weight: number): number {
const app_height: number = 1.7;
return parseFloat((app_weight / (app_height * app_height)).toFixed(1));
}
app_getBMICategory(app_bmi: number): string {
if (app_bmi < 18.5) return '偏瘦';
if (app_bmi < 24) return '正常';
if (app_bmi < 28) return '偏胖';
return '肥胖';
}
app_getBMIColor(app_bmi: number): string {
if (app_bmi < 18.5) return '#52C41A';
if (app_bmi < 24) return '#007DFF';
if (app_bmi < 28) return '#FAAD14';
return '#FF4D4F';
}
7.6 存储操作
// 保存
app_setString('weight_records', JSON.stringify(this.app_records));
app_setNumber('weight_target', this.app_targetWeight);
// 加载
const app_storedRecords: string = app_getString('weight_records', '[]');
this.app_records = JSON.parse(app_storedRecords);
this.app_targetWeight = app_getNumber('weight_target', 55);
8. 技术总结与扩展建议
8.1 技术亮点
- 声明式 UI 范式:整个界面完全采用 ArkUI 声明式语法,状态驱动渲染,代码简洁易维护
- 静态类型系统:使用 interface 定义数据结构,编译时类型检查保障代码质量
- 模块化设计:通用组件(CommonTitleBar)和工具类(AppStorage)分离复用
- BMI 健康指标:完整的 BMI 计算、分类和可视化体系
- 数据持久化:preferences API 封装合理,支持异步写入和同步读取
8.2 潜在改进点
- 身高数据:当前 BMI 计算使用硬编码身高 1.7m,应支持用户设置个人身高
- 数据导出:可增加导出 CSV/Excel 功能,方便用户在其他平台分析数据
- 图表展示:可增加体重趋势折线图,直观展示一段时间的体重变化
- 提醒功能:可结合通知能力,在设定时间提醒用户记录体重
- 数据备份:可接入云同步能力,实现多设备数据同步
8.3 ArkUI 开发经验
通过体重记录应用的分析,可以总结以下 ArkUI 开发经验:
- 优先使用
@State管理组件内状态,需要跨组件共享时考虑@StorageLink或应用级状态管理 - Slider 组件适合连续数值输入,List/Grid 适合展示列表数据,Scroll 包裹实现滚动
- 数据存储优先使用 preferences API,更复杂的需求考虑关系型数据库或分布式存储
- 颜色使用
$r('app.color.xxx')引用资源定义,便于主题切换和深色模式支持 - 生命周期方法中执行初始化和清理工作,注意异步操作的时序问题
结语
体重记录应用虽然功能简单,但涵盖了 HarmonyOS 应用开发的多个核心知识点:界面组件使用、状态管理、数据存储、业务逻辑封装、算法实现等。通过对该应用的深入分析,可以掌握 ArkUI 声明式开发的基本范式,为开发更复杂的 HarmonyOS 应用打下坚实基础。
应用的模块化架构和清晰的代码组织方式,使其成为一个良好的学习参考案例。建议读者在实际开发中借鉴其设计思路,并根据自己的业务需求进行扩展和优化。
更多推荐



所有评论(0)