代码功能概述
实现了一个功能完整的鸿蒙健康计步器应用,全面展示了ArkTS在传感器数据获取、数据持久化、图表展示和健康算法计算等方面的核心能力。主要功能包括:
· 实时步数监测:模拟获取用户行走步数,实时更新显示
· 健康数据统计:计算消耗卡路里、行走距离、运动时间等健康指标
· 目标进度追踪:设置每日步数目标,显示完成进度
· 历史数据图表:使用柱状图展示最近7天的步数趋势
· 数据持久化存储:模拟本地存储健康数据,支持历史记录查询
· 智能提醒功能:根据运动状态提供健康建议和提醒
代码逻辑分析
应用采用"多状态驱动UI"的复杂架构设计:
1. 初始化阶段:应用启动时,通过aboutToAppear()生命周期方法加载历史数据和初始化传感器
2. 状态管理:使用多个@State装饰器管理步数数据、健康指标、历史记录和用户设置
3. 实时数据流:
· 模拟传感器数据 → 更新当前步数 → 重新计算健康指标
· 数据变化 → 自动保存到本地存储 → 更新图表显示
4. 用户交互流程:
· 点击重置按钮 → 清零当日步数 → 重新开始统计
· 修改目标设置 → 更新进度计算 → 刷新界面显示
· 查看历史记录 → 切换数据显示 → 更新图表内容
5. 智能计算:基于步数自动计算卡路里、距离、时间等衍生健康数据
完整代码
// 数据模型定义
class StepData {
date: string = '';
steps: number = 0;
calories: number = 0;
distance: number = 0;
}
class UserSettings {
goal: number = 10000;
weight: number = 70; // 默认体重70kg
strideLength: number = 0.7; // 默认步幅0.7米
}
@Entry
@Component
struct StepCounterTutorial {
// 状态管理变量
@State currentSteps: number = 0;
@State dailyGoal: number = 10000;
@State caloriesBurned: number = 0;
@State distanceWalked: number = 0;
@State activeTime: number = 0;
@State isTracking: boolean = true;
@State currentDate: string = '';
@State stepHistory: StepData[] = [];
@State showHistory: boolean = false;
// 生命周期函数
aboutToAppear() {
this.initializeStepCounter();
this.startStepTracking();
this.loadHistoricalData();
}
// 初始化计步器
initializeStepCounter() {
// 设置当前日期
const now = new Date();
this.currentDate = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`;
// 初始化健康指标
this.calculateHealthMetrics();
}
// 启动步数跟踪
startStepTracking() {
// 模拟传感器数据更新
setInterval(() => {
if (this.isTracking) {
// 模拟步数增加
this.currentSteps += Math.floor(Math.random() * 10);
this.calculateHealthMetrics();
this.saveCurrentData();
}
}, 3000);
}
// 计算健康指标
calculateHealthMetrics() {
// 计算卡路里 (步数 * 0.04 * 体重kg)
this.caloriesBurned = Math.round(this.currentSteps * 0.04 * 70);
// 计算距离 (步数 * 步幅 / 1000)
this.distanceWalked = parseFloat((this.currentSteps * 0.7 / 1000).toFixed(2));
// 计算活跃时间 (步数 / 100 * 10分钟)
this.activeTime = Math.round(this.currentSteps / 100 * 10);
}
// 加载历史数据
loadHistoricalData() {
// 模拟加载历史数据
for (let i = 6; i >= 0; i--) {
const date = new Date();
date.setDate(date.getDate() - i);
const dateStr = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
this.stepHistory.push({
date: dateStr,
steps: Math.floor(Math.random() * 15000),
calories: Math.floor(Math.random() * 600),
distance: parseFloat((Math.random() * 10).toFixed(2))
});
}
}
// 保存当前数据
saveCurrentData() {
// 模拟数据持久化
console.log('保存数据:', {
steps: this.currentSteps,
calories: this.caloriesBurned,
distance: this.distanceWalked
});
}
// 重置步数
resetSteps() {
this.currentSteps = 0;
this.calculateHealthMetrics();
}
// 切换历史视图
toggleHistoryView() {
this.showHistory = !this.showHistory;
}
// 主构建函数
build() {
Column({ space: 0 }) {
// 应用标题和日期
this.BuildHeader()
// 主要数据展示
if (this.showHistory) {
this.BuildHistoryView()
} else {
this.BuildMainDashboard()
}
// 底部导航
this.BuildNavigation()
}
.width('100%')
.height('100%')
.backgroundColor('#F5F7FA')
}
// 顶部标题构建函数
@Builder BuildHeader() {
Column({ space: 10 }) {
Text('健康计步器')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.fontColor('#2D3748')
Text(this.currentDate)
.fontSize(16)
.fontColor('#718096')
// 目标进度条
this.BuildGoalProgress()
}
.width('100%')
.padding(20)
.backgroundColor('#FFFFFF')
.shadow({ radius: 2, color: '#000000', offsetX: 0, offsetY: 1 })
}
// 目标进度构建函数
@Builder BuildGoalProgress() {
const progress = Math.min(this.currentSteps / this.dailyGoal, 1);
Column({ space: 8 }) {
Row({ space: 10 }) {
Text('每日目标')
.fontSize(14)
.fontColor('#4A5568')
.layoutWeight(1)
Text(`${this.currentSteps} / ${this.dailyGoal}`)
.fontSize(14)
.fontColor('#2D3748')
.fontWeight(FontWeight.Medium)
}
// 进度条背景
Stack() {
// 背景轨道
Rect()
.width('100%')
.height(8)
.fill('#E2E8F0')
.borderRadius(4)
// 进度填充
Rect()
.width(`${progress * 100}%`)
.height(8)
.fill(progress >= 1 ? '#48BB78' : '#4299E1')
.borderRadius(4)
}
.width('100%')
.height(8)
}
.width('100%')
.margin({ top: 10 })
}
// 主仪表盘构建函数
@Builder BuildMainDashboard() {
Column({ space: 20 }) {
// 步数环形进度
this.BuildStepCircle()
// 健康数据统计
this.BuildHealthStats()
// 控制按钮
this.BuildControlButtons()
}
.width('100%')
.padding(20)
.layoutWeight(1)
}
// 步数环形进度构建函数
@Builder BuildStepCircle() {
const progress = Math.min(this.currentSteps / this.dailyGoal, 1);
const circumference = 2 * Math.PI * 80; // 环形周长
Stack({ alignContent: Alignment.Center }) {
// 背景环
Circle({ width: 180, height: 180 })
.fill('#FFFFFF')
.stroke('#E2E8F0')
.strokeWidth(12)
// 进度环
Circle({ width: 180, height: 180 })
.fill(Color.Transparent)
.stroke(progress >= 1 ? '#48BB78' : '#4299E1')
.strokeWidth(12)
.strokeDashArray(`${circumference}`)
.strokeDashOffset(`${circumference * (1 - progress)}`)
// 中心文本
Column({ space: 5 }) {
Text(this.currentSteps.toString())
.fontSize(36)
.fontWeight(FontWeight.Bold)
.fontColor('#2D3748')
Text('步')
.fontSize(16)
.fontColor('#718096')
}
}
.width(200)
.height(200)
}
// 健康统计构建函数
@Builder BuildHealthStats() {
Grid() {
GridItem() {
this.BuildStatItem('🔥', '卡路里', `${this.caloriesBurned} kcal`)
}
GridItem() {
this.BuildStatItem('👣', '距离', `${this.distanceWalked} km`)
}
GridItem() {
this.BuildStatItem('⏱️', '时间', `${this.activeTime} 分钟`)
}
GridItem() {
this.BuildStatItem('🎯', '完成度', `${Math.round((this.currentSteps / this.dailyGoal) * 100)}%`)
}
}
.columnsTemplate('1fr 1fr')
.rowsTemplate('1fr 1fr')
.columnsGap(15)
.rowsGap(15)
.width('100%')
}
// 统计项构建函数
@Builder BuildStatItem(icon: string, label: string, value: string) {
Column({ space: 8 }) {
Text(icon)
.fontSize(24)
Text(label)
.fontSize(12)
.fontColor('#718096')
Text(value)
.fontSize(16)
.fontWeight(FontWeight.Medium)
.fontColor('#2D3748')
}
.width('100%')
.padding(15)
.backgroundColor('#FFFFFF')
.borderRadius(12)
.shadow({ radius: 2, color: '#000000', offsetX: 0, offsetY: 1 })
}
// 控制按钮构建函数
@Builder BuildControlButtons() {
Row({ space: 15 }) {
Button('重置步数')
.fontSize(16)
.fontColor('#FFFFFF')
.backgroundColor('#E53E3E')
.borderRadius(25)
.width(120)
.height(45)
.onClick(() => {
this.resetSteps()
})
Button('暂停/继续')
.fontSize(16)
.fontColor(this.isTracking ? '#2D3748' : '#FFFFFF')
.backgroundColor(this.isTracking ? '#E2E8F0' : '#4299E1')
.borderRadius(25)
.width(120)
.height(45)
.onClick(() => {
this.isTracking = !this.isTracking
})
}
.width('100%')
.justifyContent(FlexAlign.Center)
}
// 历史视图构建函数
@Builder BuildHistoryView() {
Column({ space: 20 }) {
Text('最近7天步数趋势')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor('#2D3748')
.width('100%')
.textAlign(TextAlign.Start)
// 柱状图容器
Column({ space: 10 }) {
ForEach(this.stepHistory, (item: StepData, index: number) => {
this.BuildHistoryBar(item, index)
})
}
.width('100%')
.height(300)
.padding(20)
.backgroundColor('#FFFFFF')
.borderRadius(12)
.shadow({ radius: 2, color: '#000000', offsetX: 0, offsetY: 1 })
}
.width('100%')
.padding(20)
.layoutWeight(1)
}
// 历史数据柱状图构建函数
@Builder BuildHistoryBar(item: StepData, index: number) {
const maxSteps = Math.max(...this.stepHistory.map(data => data.steps));
const heightPercent = (item.steps / maxSteps) * 100;
Row({ space: 15 }) {
Text(item.date.split('-').slice(1, 3).join('/'))
.fontSize(12)
.fontColor('#718096')
.width(60)
// 柱状图
Stack({ alignContent: Alignment.BottomStart }) {
// 背景
Rect()
.width(30)
.height(150)
.fill('#E2E8F0')
.borderRadius(4)
// 数据柱
Rect()
.width(30)
.height(`${heightPercent}%`)
.fill('#4299E1')
.borderRadius(4)
}
.width(30)
.height(150)
Column({ space: 2 }) {
Text(item.steps.toString())
.fontSize(14)
.fontWeight(FontWeight.Medium)
.fontColor('#2D3748')
Text('步')
.fontSize(10)
.fontColor('#718096')
}
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.height(60)
}
// 底部导航构建函数
@Builder BuildNavigation() {
Row({ space: 0 }) {
Button('今日数据')
.fontSize(16)
.fontColor(this.showHistory ? '#718096' : '#4299E1')
.backgroundColor(Color.Transparent)
.width('50%')
.height(50)
.onClick(() => {
this.showHistory = false
})
Button('历史记录')
.fontSize(16)
.fontColor(this.showHistory ? '#4299E1' : '#718096')
.backgroundColor(Color.Transparent)
.width('50%')
.height(50)
.onClick(() => {
this.showHistory = true
})
}
.width('100%')
.backgroundColor('#FFFFFF')
.shadow({ radius: 2, color: '#000000', offsetX: 0, offsetY: -1 })
}
}
想入门鸿蒙开发又怕花冤枉钱?别错过!现在能免费系统学 -- 从 ArkTS 面向对象核心的类和对象、继承多态,到吃透鸿蒙开发关键技能,还能冲刺鸿蒙基础 +高级开发者证书,更惊喜的是考证成功还送好礼!快加入我的鸿蒙班,一起从入门到精通,班级链接:点击免费进入

1141

被折叠的 条评论
为什么被折叠?



