HarmonyOS ArkTS 实战:实现一个BMI健康计算器
HarmonyOS ArkTS 实战:实现一个BMI健康计算器
项目效果
本文实现的是一个基于 HarmonyOS 和 ArkTS 的BMI健康计算器。项目中使用 ArkUI 组件完成页面布局,通过 @State 管理状态数据,实现身高体重输入、性别选择、实时BMI计算、健康状态评估、健康建议和理想体重范围等功能。
最终运行效果如下:
页面主要包含以下内容:
- 顶部应用标题;
- 性别选择(男/女);
- 身高输入(厘米);
- 体重输入(公斤);
- BMI结果大字体显示;
- 健康状态颜色指示;
- 健康建议文字;
- 理想体重范围;
- BMI范围参考说明;
- 页面整体采用 ArkUI 声明式布局。
本文重点是演示如何在 HarmonyOS 项目中使用 ArkTS 和 ArkUI 实现一个健康计算类单页面应用。项目代码主要写在 entry/src/main/ets/pages/Index.ets 文件中,适合作为 HarmonyOS ArkTS 入门到进阶之间的练习案例。
前言
身体质量指数(BMI)是国际通用的衡量人体胖瘦程度以及是否健康的标准。通过BMI可以快速了解自己的体重是否在健康范围内,对于健康管理非常有帮助。手动计算BMI很简单,但一个好的计算器还能给出健康状态评估和建议。
从应用开发角度来看,这个项目不依赖后端接口,也不需要数据库,但能练习 ArkTS 中的状态管理、性别选择、数字输入、实时计算、条件判断和结果展示等内容。
本文基于 HarmonyOS 和 ArkTS 实现一个BMI健康计算器。用户可以输入性别、身高和体重,实时计算BMI值,查看健康状态,获取健康建议和理想体重范围。
这个项目的核心不是简单的BMI公式,而是完整的健康评估和友好的用户体验。每一次输入变化,都会实时重新计算并给出反馈,这正是 ArkUI 声明式开发的基本思想。
一、项目目标
本次实践主要实现以下目标:
- 创建 HarmonyOS ArkTS 页面;
- 使用
@Entry和@Component定义页面组件; - 使用
@State管理页面状态; - 实现男女性别选择;
- 身高和体重数字输入;
- 实时计算BMI值;
- 根据BMI判断健康状态;
- 不同状态显示不同颜色;
- 给出针对性健康建议;
- 计算理想体重范围;
- 显示BMI参考范围说明;
- 使用
@Builder封装性别选择按钮和结果卡片; - 完成一个可以运行的BMI计算器页面。
这个项目虽然是单页面应用,但它实现了完整的BMI计算和健康评估功能,比普通静态页面更适合练习 ArkTS。
二、技术栈
| 类型 | 内容 |
|---|---|
| 开发方向 | HarmonyOS 应用开发 |
| 开发语言 | ArkTS |
| UI 框架 | ArkUI |
| SDK 版本 | HarmonyOS API 23 及以上 |
| 工程模型 | Stage 模型 |
| 核心组件 | Text / TextInput / Button / Column / Row / Slider |
| 状态管理 | @State |
| 数据处理 | BMI计算 / 健康评估 / 实时响应 |
| 项目入口 | entry/src/main/ets/pages/Index.ets |
| 运行平台 | 模拟器或真机 |
本项目是 HarmonyOS 原生 ArkTS 项目。页面主体由 ArkUI 组件构建,核心逻辑写在 Index.ets 文件中,不依赖后端接口,也不需要额外配置数据库。
三、为什么选择BMI计算器项目
BMI健康计算器适合作为 ArkTS 练习项目,主要有以下几个原因。
第一,实用性强。BMI计算是健康管理的基础,很多人都会用到。
第二,业务场景真实。关注健康的人都需要了解自己的BMI,是非常实用的健康工具。
第三,适合练习状态管理。性别、身高、体重都属于页面状态。状态变化后,页面会自动刷新。
第四,适合练习条件判断。根据BMI值区间判断健康状态,给出不同建议和颜色。
第五,适合练习实时计算。输入变化时立即计算结果,提供流畅体验。
第六,扩展空间比较大。基础功能完成后,可以继续增加体脂率计算、基础代谢计算、卡路里计算、历史记录和健康趋势图。
在本项目中,身高体重和性别是核心数据。所有计算结果和健康评估都基于这些数据。
四、功能规则说明
BMI计算公式:BMI = 体重(kg) / (身高(m))²
中国成年人BMI标准:
| BMI范围 | 状态 | 颜色 |
|---|---|---|
| < 18.5 | 偏瘦 | #3B82F6(蓝色) |
| 18.5 - 23.9 | 正常 | #10B981(绿色) |
| 24 - 27.9 | 偏胖 | #F59E0B(橙色) |
| ≥ 28 | 肥胖 | #EF4444(红色) |
理想体重范围:18.5 ≤ BMI ≤ 23.9 对应的体重范围。
默认参数:
- 性别:男
- 身高:170cm
- 体重:65kg
五、项目结构
本项目主要修改首页文件:
entry
└── src
└── main
└── ets
└── pages
└── Index.ets
其中:
| 文件 | 作用 |
|---|---|
| Index.ets | 编写页面结构、状态数据和BMI计算逻辑 |
本文不涉及复杂路由,也不需要额外创建多个页面。对于练习项目来说,把主要逻辑集中在一个 Index.ets 文件中更方便理解。
六、核心实现思路
本项目的核心流程如下:
- 使用
@State保存性别、身高、体重; - 用户选择性别;
- 用户输入身高(厘米);
- 用户输入体重(公斤);
- 参数变化时自动计算BMI;
- 根据BMI值判断健康状态;
- 根据状态显示对应颜色和建议;
- 计算理想体重范围;
- 显示BMI参考标准说明。
项目中最重要的状态变量如下:
@State gender: number = 0
@State height: string = '170'
@State weight: string = '65'
其中:
| 状态变量 | 作用 |
|---|---|
| gender | 性别(0=男,1=女) |
| height | 身高(厘米) |
| weight | 体重(公斤) |
这些参数是计算的基础,任何一个变化都会触发重新计算。
七、Index.ets 完整代码
打开文件:
entry/src/main/ets/pages/Index.ets
将其中内容替换为下面代码:
@Entry
@Component
struct Index {
@State gender: number = 0
@State height: string = '170'
@State weight: string = '65'
private getBMI(): number {
let h = parseFloat(this.height)
let w = parseFloat(this.weight)
if (isNaN(h) || isNaN(w) || h <= 0 || w <= 0) return 0
let heightM = h / 100
return w / (heightM * heightM)
}
private getBMIStatus(): { status: string, color: string, advice: string } {
let bmi = this.getBMI()
if (bmi === 0) return { status: '请输入数据', color: '#9CA3AF', advice: '请输入有效的身高和体重' }
if (bmi < 18.5) {
return {
status: '偏瘦',
color: '#3B82F6',
advice: '您的体重偏轻,建议适当增加营养,均衡饮食,加强锻炼增强体质。'
}
}
if (bmi < 24) {
return {
status: '正常',
color: '#10B981',
advice: '恭喜!您的体重在正常范围内,请继续保持健康的生活习惯。'
}
}
if (bmi < 28) {
return {
status: '偏胖',
color: '#F59E0B',
advice: '您的体重略微超标,建议控制饮食,减少高热量食物摄入,增加运动量。'
}
}
return {
status: '肥胖',
color: '#EF4444',
advice: '您的体重已达到肥胖标准,建议制定科学的减重计划,必要时咨询医生。'
}
}
private getIdealWeightRange(): string {
let h = parseFloat(this.height)
if (isNaN(h) || h <= 0) return '-'
let heightM = h / 100
let minWeight = 18.5 * heightM * heightM
let maxWeight = 23.9 * heightM * heightM
return `${minWeight.toFixed(1)} - ${maxWeight.toFixed(1)} kg`
}
@Builder
GenderButton(text: string, icon: string, index: number) {
Column() {
Text(icon)
.fontSize(40)
.margin({ bottom: 8 })
Text(text)
.fontSize(16)
.fontColor(this.gender === index ? Color.White : '#4B5563')
}
.width('48%')
.height(100)
.justifyContent(FlexAlign.Center)
.backgroundColor(this.gender === index ? '#0A59F7' : '#F3F4F6')
.borderRadius(16)
.onClick(() => {
this.gender = index
})
}
@Builder
BMIRangeItem(range: string, status: string, color: string) {
Row() {
Circle()
.width(12)
.height(12)
.fill(color)
Text(range)
.fontSize(14)
.fontColor('#182431')
.margin({ left: 8 })
Blank()
Text(status)
.fontSize(14)
.fontColor(color)
}
.width('100%')
.padding({ top: 8, bottom: 8 })
}
build() {
Column() {
Text('BMI计算器')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.fontColor('#182431')
.margin({ top: 22 })
Text('基于 HarmonyOS ArkTS 的健康评估工具')
.fontSize(14)
.fontColor('#6B7280')
.margin({ top: 8, bottom: 20 })
Column() {
Text('选择性别')
.fontSize(16)
.fontWeight(FontWeight.Medium)
.fontColor('#182431')
.width('100%')
.margin({ bottom: 12 })
Row() {
this.GenderButton('男生', '👨', 0)
Blank().width(16)
this.GenderButton('女生', '👩', 1)
}
.width('100%')
}
.width('100%')
.padding(16)
.backgroundColor(Color.White)
.borderRadius(16)
.margin({ bottom: 16 })
.shadow({
radius: 8,
color: '#08000000',
offsetX: 0,
offsetY: 2
})
Column() {
Text('身高体重')
.fontSize(16)
.fontWeight(FontWeight.Medium)
.fontColor('#182431')
.width('100%')
.margin({ bottom: 12 })
Row() {
Text('身高')
.fontSize(15)
.fontColor('#182431')
.width(60)
TextInput({
text: this.height,
placeholder: '身高'
})
.layoutWeight(1)
.height(44)
.fontSize(16)
.textAlign(TextAlign.End)
.backgroundColor('#F5F7FA')
.borderRadius(12)
.padding({ left: 12, right: 12 })
.type(InputType.Number)
.onChange((value: string) => {
this.height = value
})
Text('cm')
.fontSize(15)
.fontColor('#6B7280')
.margin({ left: 8 })
}
.width('100%')
.margin({ bottom: 12 })
Row() {
Text('体重')
.fontSize(15)
.fontColor('#182431')
.width(60)
TextInput({
text: this.weight,
placeholder: '体重'
})
.layoutWeight(1)
.height(44)
.fontSize(16)
.textAlign(TextAlign.End)
.backgroundColor('#F5F7FA')
.borderRadius(12)
.padding({ left: 12, right: 12 })
.type(InputType.Number)
.onChange((value: string) => {
this.weight = value
})
Text('kg')
.fontSize(15)
.fontColor('#6B7280')
.margin({ left: 8 })
}
.width('100%')
}
.width('100%')
.padding(16)
.backgroundColor(Color.White)
.borderRadius(16)
.margin({ bottom: 16 })
.shadow({
radius: 8,
color: '#08000000',
offsetX: 0,
offsetY: 2
})
Column() {
Text('您的BMI')
.fontSize(14)
.fontColor('#6B7280')
.margin({ bottom: 8 })
Text(this.getBMI().toFixed(1))
.fontSize(56)
.fontWeight(FontWeight.Bold)
.fontColor(this.getBMIStatus().color)
Text(this.getBMIStatus().status)
.fontSize(20)
.fontWeight(FontWeight.Medium)
.fontColor(this.getBMIStatus().color)
.margin({ top: 4 })
Text(this.getBMIStatus().advice)
.fontSize(14)
.fontColor('#6B7280')
.textAlign(TextAlign.Center)
.lineHeight(22)
.margin({ top: 12 })
.padding({ left: 20, right: 20 })
}
.width('100%')
.padding(24)
.backgroundColor(Color.White)
.borderRadius(16)
.margin({ bottom: 16 })
.shadow({
radius: 8,
color: '#08000000',
offsetX: 0,
offsetY: 2
})
Column() {
Row() {
Text('理想体重范围')
.fontSize(14)
.fontColor('#6B7280')
Blank()
Text(this.getIdealWeightRange())
.fontSize(16)
.fontWeight(FontWeight.Medium)
.fontColor('#10B981')
}
.width('100%')
.padding({ bottom: 12 })
.border({ width: { bottom: 1 }, color: '#F3F4F6' })
Text('BMI参考标准(中国成年人)')
.fontSize(13)
.fontColor('#9CA3AF')
.width('100%')
.margin({ top: 12, bottom: 8 })
this.BMIRangeItem('< 18.5', '偏瘦', '#3B82F6')
this.BMIRangeItem('18.5 - 23.9', '正常', '#10B981')
this.BMIRangeItem('24.0 - 27.9', '偏胖', '#F59E0B')
this.BMIRangeItem('≥ 28.0', '肥胖', '#EF4444')
}
.width('100%')
.padding(16)
.backgroundColor(Color.White)
.borderRadius(16)
.shadow({
radius: 8,
color: '#08000000',
offsetX: 0,
offsetY: 2
})
Text('* 本工具仅供参考,不能替代专业医疗建议')
.fontSize(12)
.fontColor('#9CA3AF')
.margin({ top: 16 })
}
.width('100%')
.height('100%')
.padding({ left: 18, right: 18 })
.backgroundColor('#F5F7FA')
}
}
八、代码实现说明
1. BMI计算
使用标准BMI公式计算:体重(kg)除以身高(m)的平方:
let heightM = h / 100
return w / (heightM * heightM)
2. 健康状态评估
根据中国成年人BMI标准判断健康状态,返回状态文字、颜色和建议:
- <18.5:偏瘦,蓝色,建议增加营养
- 18.5-23.9:正常,绿色,建议保持
- 24-27.9:偏胖,橙色,建议控制饮食
- ≥28:肥胖,红色,建议减重
3. 理想体重范围
根据身高计算BMI在18.5-23.9之间对应的体重范围,给用户参考。
4. 性别选择
使用大按钮选择男女性别,选中状态用蓝色背景白色文字,直观清晰。
5. 实时计算
身高或体重变化时立即重新计算BMI和所有结果,不需要点击按钮。
6. 颜色反馈
不同健康状态使用不同颜色显示结果,直观醒目:正常绿色、偏胖橙色、肥胖红色、偏瘦蓝色。
九、运行项目
代码编写完成后,在DevEco Studio中运行项目。测试不同身高体重输入,验证BMI计算是否正确,检查健康状态判断和建议是否准确,理想体重范围是否正确。
十、开发中遇到的问题
- 单位转换:身高输入是厘米,计算时要转换成米
- 输入验证:处理空输入和非法输入,避免NaN
- 中国标准:使用中国成年人BMI标准,而不是国际标准
- 建议个性化:根据不同状态给出针对性的健康建议
十一、总结
本文基于HarmonyOS和ArkTS实现了一个BMI健康计算器。项目通过@State管理输入参数,使用标准BMI公式计算,实现了实时健康评估、状态颜色指示和个性化建议。这个项目展示了ArkTS中表单输入、条件判断和实时计算的基本方法,适合作为入门练习项目。
更多推荐

所有评论(0)