发布时间:2026/7/12 9:02:02
HarmonyOS运动健康——训练页面交互与动作详情
从训练页面点击一个动作跳转到动作详情页。这个流程涉及两个页面的数据传递和交互衔接WorkoutPage负责展示动作列表和训练计划选择ExerciseDetail负责展示单个动作的完整信息。两个页面通过路由参数连接——WorkoutPage传入动作IDExerciseDetail根据ID加载数据。完整效果WorkoutPage训练计划选择与动作列表计划选择器的交互训练计划选择器是横向滚动的Row每个计划卡片固定100px宽。选中状态通过两个属性区分背景色从白色变成半透明彩色边框从1px浅灰变成1.5px彩色。.backgroundColor(this.selectedPlan plan.id ? plan.color 15 : CW) .border({ width: this.selectedPlan plan.id ? 1.5 : 1, color: this.selectedPlan plan.id ? plan.color : #F0EEF4 })点击卡片时做两件事更新selectedPlan触发UI重渲染同时调用getExercisesForPlan(plan)更新动作列表。但从截图来看切换计划后动作列表没有变化——这可能是因为ForEach用的是EXERCISES全局数组而不是this.planExercises当前计划的动作。动作列表的布局每个动作行是Row结构左侧56×56图标 中间三行信息 右侧箭头。信息区的三行文字是动作名称14px加粗深色——最醒目用户第一眼看到目标肌群11px灰色maxLines:1——次要信息截断不影响理解训练详情行红色难度标签 灰色时长 灰色卡路里——三个属性用文字拼接Row() { Text(ex.difficulty).fontSize(10).fontColor(A) .padding({ left: 6, right: 6, top: 1, bottom: 1 }) .backgroundColor(#FFF0F0).borderRadius(4) Text( ex.duration 分钟).fontSize(10).fontColor(T2) Text( · ex.calories 千卡).fontSize(10).fontColor(T2) }.margin({ top: 4 })难度标签用红色文字浅红背景视觉上最醒目。时长和卡路里用灰色小字视觉层级较低。这种难度突出、数据弱化的设计让用户快速判断这个动作难不难而不是纠结具体数字。点击跳转.onClick(() { router.pushUrl({ url: pages/ExerciseDetail, params: { id: ex.id } as Recordstring,Object }) })点击动作行跳转到ExerciseDetail页面传入id参数。as Recordstring,Object是类型断言——router.getParams()返回的是Recordstring, Object需要断言才能访问具体字段。从截图来看训练计划页面有三个计划卡片7分钟晨练、核心强化、力量突破下方是六个动作俯卧撑、深蹲、平板支撑、波比跳、哑铃弯举、仰卧起坐。选中核心强化时卡片有绿色边框和浅绿背景。ExerciseDetail动作详情页数据加载State ex: Exercise | undefined undefined aboutToAppear(): void { const p router.getParams() as Recordstring, Object if (p p[id]) this.ex getExerciseById(p[id] as number) }从路由参数中读取id调用getExerciseById(id)获取动作数据。State ex初始值是undefined——如果路由参数中没有id或者找不到对应的动作页面不会渲染任何内容。这里有一个防御性设计if (this.ex)条件渲染整个页面内容。如果ex是undefined页面只显示空的Column和背景色。不会崩溃但用户看到的是空白页面——更好的做法是显示动作不存在的提示。页面结构Column() { // Header返回按钮标题 if (this.ex) { Scroll() { Column() { // 图标区 // 标签行 // 目标肌群 // 动作步骤 } } } }和WorkoutPage一样的Header结构左侧返回按钮右侧标题。但ExerciseDetail没有底部导航栏——它是子页面用户看完详情后返回WorkoutPage不需要底部导航。图标区Text(this.ex.icon).fontSize(80).width(100%).height(160).textAlign(TextAlign.Center) .backgroundColor(#F5F5F7).borderRadius(20)80px的emoji图标放在160px高的浅灰色区域内。textAlign(TextAlign.Center)让emoji水平居中Column的默认垂直居中让emoji垂直居中。borderRadius(20)让灰色区域有圆角。这个区域占据了屏幕上半部分的大量空间——目的是让用户一眼看到这是什么动作。emoji在不同设备上的渲染效果不同但80px的大尺寸能保证辨识度。标签行Row() { this.Tag(⏱ this.ex.duration 分钟, A) this.Tag( this.ex.calories 千卡, #FF9F43) this.Tag( this.ex.difficulty, #5DADE2) }.width(100%).margin({ top: 16, bottom: 12 }).justifyContent(FlexAlign.Start)三个标签横向排列分别用红、橙、蓝色。每个标签是emoji文字的组合和训练计划页面的难度标签类似但更大fontSize: 12, padding: 10×5。Tag BuilderBuilder Tag(text: string, color: string) { Text(text).fontSize(12).fontColor(color).padding({ left: 10, right: 10, top: 5, bottom: 5 }) .backgroundColor(color 12).borderRadius(8).margin({ right: 8 }) }Tag Builder接收文本和颜色生成一个带圆角背景的标签。color 12是约7%透明度的彩色背景margin({ right: 8 })让标签之间有间距。这个Builder的设计和WorkoutPage的难度标签思路一致——用color 十六进制透明度做背景色。但ExerciseDetail的标签更大padding 10×5 vs 6×1因为详情页有更多空间。目标肌群Text(目标肌群).fontSize(16).fontWeight(FontWeight.Bold).fontColor(T1).width(100%).margin({ bottom: 8 }) Text(this.ex.muscles).fontSize(14).fontColor(T2)两行文字标题16px加粗 内容14px灰色。标题用width(100%)确保占满整行内容紧跟其后。从截图来看“目标肌群显示为胸肌·肱三头肌·核心”——用中文中间点分隔多个肌群。这是WorkoutData中定义的数据格式详情页直接展示。动作步骤Text(动作步骤).fontSize(16).fontWeight(FontWeight.Bold).fontColor(T1).width(100%).margin({ top: 16, bottom: 10 }) ForEach(this.ex.steps, (step: string, idx: number) { Row() { Column() { Text((idx1).toString()).fontSize(12).fontWeight(FontWeight.Bold).fontColor(Color.White) } .width(24).height(24).borderRadius(12).backgroundColor(A) .justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center) Text(step).fontSize(14).fontColor(T1).margin({ left: 12 }).layoutWeight(1) }.width(100%).padding(12).backgroundColor(#FFFFFF).borderRadius(12).margin({ bottom: 8 }) })每个步骤由两部分组成左侧红色圆形编号 右侧步骤文字。红色圆形编号24×24的红色圆形居中显示白色数字。borderRadius(12)是宽度的一半确保是正圆。justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)让数字在圆形内居中。步骤文字14px深色文字margin({ left: 12 })和编号保持间距layoutWeight(1)占据剩余空间。步骤卡片每个步骤是白色背景12px圆角12px内边距。步骤之间用margin({ bottom: 8 })分隔。从截图来看俯卧撑有四个步骤双手撑地与肩同宽身体保持直线屈肘下降至胸部接近地面推起回到起始位置每个步骤卡片独立视觉上像任务清单——用户可以逐个步骤阅读完成后在心里打勾。两个页面的数据流首页 → [点击训练卡片] → WorkoutPage → [点击动作行] → ExerciseDetail 传入planId 传入id数据流是单向的首页传planId给WorkoutPageWorkoutPage传id给ExerciseDetail。每个页面只接收自己需要的数据不依赖上上个页面的状态。WorkoutPage的aboutToAppear接收planId后设置selectedPlanWorkoutData根据planId返回对应的训练计划。ExerciseDetail的aboutToAppear接收id后调用getExerciseById(id)获取动作详情。这种逐级传递的模式比全局状态更简单——不需要AppStorage或PersistentStorage每个页面只关心自己的路由参数。缺点是如果需要跨页面共享数据比如用户正在训练的动作就需要额外的状态管理方案。踩坑记录ex的undefined处理。State ex: Exercise | undefined undefined初始值是undefinedaboutToAppear中如果找不到对应的动作ex保持undefined。页面的if (this.ex)条件渲染避免了崩溃但用户看到的是空白页面。更好的做法是显示一个动作不存在的提示或者用router.back()返回上一页。emoji在不同设备的渲染差异。标签行用emoji⏱代替图标。emoji在不同鸿蒙设备上可能显示为不同样式——有些是彩色的有些是黑白的。如果要上线需要用SymbolGlyph或自定义图标替代。步骤编号的居中实现。红色圆形编号用justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)实现居中。Column的默认方向是垂直的justifyContent控制垂直居中alignItems控制水平居中。如果用Row而不是Column居中逻辑会反过来。训练详情行的字符串拼接。WorkoutPage中动作列表的训练详情行用字符串拼接 ex.duration 分钟和 · ex.calories 千卡。前面的空格和中间点是分隔符但空格宽度受字体影响不够精确。ExerciseDetail的标签用独立的Tag Builder每个标签有自己的padding和margin间距更可控。滚动区域的高度计算。ExerciseDetail的Scroll占据layoutWeight(1)——扣除Header后的全部空间。Scroll内部的Column没有固定高度会根据内容自动撑开。如果内容超过屏幕高度Scroll会处理滚动。但如果内容太少比如只有两三个步骤底部会有大量空白。Blank().height(30)在底部加了30px的间距避免最后一个步骤卡片紧贴屏幕底部。训练页面到动作详情的跳转是运动健康App的核心交互路径。WorkoutPage负责选择选计划、选动作ExerciseDetail负责展示展示完整信息。两个页面通过路由参数连接数据单向流动各自只关心自己的职责。这种选择→详情的模式在几乎所有App中都存在——电商的商品列表→商品详情、新闻的文章列表→文章详情——核心逻辑是一样的列表页承载浏览和筛选详情页承载深度阅读和操作。

相关新闻

Unity图集打包冗余:内存暴涨的根源分析与根治方案
2026/7/12 9:02:02

Unity图集打包冗余:内存暴涨的根源分析与根治方案

1. 项目概述:当你的游戏内存悄然“膨胀”如果你是一名Unity开发者,尤其是负责过UI模块或者2D项目,那么“内存暴涨”这个词很可能让你心头一紧。在项目开发中后期,特别是资源整合与打包阶段,一个隐蔽却致命的问题常常浮…

阅读更多
UE5 VR一体机开发环境搭建:从Android配置到打包部署全流程实战
2026/7/12 9:02:02

UE5 VR一体机开发环境搭建:从Android配置到打包部署全流程实战

1. 项目概述:为什么UE5 VR一体机开发是个“技术深水区”?如果你是一名游戏开发者或者数字孪生领域的从业者,最近想把项目从PC VR搬到VR一体机上,大概率会第一时间想到虚幻引擎5(UE5)。毕竟,它的…

阅读更多
TLA2518 ADC与PIC32MX675F256L的硬件设计与SPI通信优化
2026/7/12 9:02:02

TLA2518 ADC与PIC32MX675F256L的硬件设计与SPI通信优化

1. TLA2518与PIC32MX675F256L的硬件架构解析 TLA2518是德州仪器推出的一款8通道12位1MSPS SAR型ADC,采用WQFN-16封装(33mm)。这款芯片最显著的特点是每个通道可独立配置为模拟输入、数字输入或数字输出,实现了ADC与GPIO的灵活组合…

阅读更多
2025年自动驾驶算法工程师实战指南:L2/L3落地关键链路拆解
2026/7/12 10:02:02

2025年自动驾驶算法工程师实战指南:L2/L3落地关键链路拆解

1. 这不是职业展望,而是一份2025年自动驾驶算法工程师的实操日志“一个普通自动驾驶算法工程师的2025年”——这个标题里没有宏大叙事,没有技术布道,也没有PPT式的职业规划。它就是一张被咖啡渍洇湿的工位便签,上面记着昨天调试失…

阅读更多
华为云 CodeArts Req 敏捷实战:3步完成凤凰商城 Epic 到 Task 的思维导图规划
2026/7/12 10:02:02

华为云 CodeArts Req 敏捷实战:3步完成凤凰商城 Epic 到 Task 的思维导图规划

华为云CodeArts Req敏捷实战:3步构建凤凰商城需求分解思维导图 在电商项目快速迭代的开发节奏中,如何将宏观的商业需求精准拆解为可执行的技术任务,是每个敏捷团队面临的挑战。华为云CodeArts Req的思维导图规划功能,通过可视化的…

阅读更多
Node.js 18 + node-gyp 10.3.0 Windows 11 环境配置:3步解决 Visual Studio 未找到错误
2026/7/12 10:02:02

Node.js 18 + node-gyp 10.3.0 Windows 11 环境配置:3步解决 Visual Studio 未找到错误

Node.js 18 node-gyp 10.3.0 Windows 11 环境配置终极指南 当你在Windows 11上尝试构建Node.js原生模块时,是否曾被 msvs_version not set 错误拦住了脚步?这个问题困扰着无数开发者,特别是当你使用较新的Node.js 18和node-gyp 10.3.0组合…

阅读更多
四足机器人价格对比:宇树B2与云深处X20的全周期价值拆解
2026/7/12 10:02:02

四足机器人价格对比:宇树B2与云深处X20的全周期价值拆解

1. 项目概述:四足机器人市场里的“性价比”之争,到底在比什么?“跟宇树一比,云深处太贵了?”——这句话最近在机器人爱好者群、高校实验室讨论组和工业自动化采购圈里反复刷屏。它不是一句简单的吐槽,而是当…

阅读更多
自动驾驶3D感知中匈牙利匹配的原理、实现与工程落地
2026/7/12 10:02:02

自动驾驶3D感知中匈牙利匹配的原理、实现与工程落地

1. 为什么3D感知里必须用匈牙利匹配——不是“选它”,而是“没得选”在自动驾驶感知系统里,你见过最让人抓狂的场景是什么?不是模型跑不起来,也不是显存爆了,而是训练时loss曲线明明一路往下走,mAP却卡在52…

阅读更多
HarmonyOS运动健康——运动记录与统计概览页面
2026/7/12 9:02:02

HarmonyOS运动健康——运动记录与统计概览页面

进度页面是运动健康App的数据汇总页。用户从首页点击"运动记录"或底部导航"进度"跳转到这里,查看本周的运动数据和统计概览。这个页面的任务是:把散落在各处的运动数据(步数、卡路里、时长、次数)汇总成直观的…

阅读更多
智慧树刷课插件:5分钟实现自动化学习的智能助手
2026/7/12 0:01:57

智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 智慧树刷课插件是一款专为智慧树在线教育平台设计的Chrome浏…

阅读更多
Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案
2026/7/12 0:01:57

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否在GOG或Epic Games Store购买了心仪的游戏…

阅读更多
办公自动化实战:5个免费工具构建合同处理流水线
2026/7/12 0:01:57

办公自动化实战:5个免费工具构建合同处理流水线

1. 这不是“又一个工具包”,而是一套经过237次真实场景验证的效率组合拳“2026.04.28实用教程工具分享”这个标题乍看平平无奇,像极了你邮箱里被自动归入“促销/订阅”文件夹的那类通知——但如果你真把它当普通更新忽略,接下来半年里&#x…

阅读更多
智慧树刷课插件:5分钟实现自动化学习的智能助手
2026/7/12 0:01:57

智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 智慧树刷课插件是一款专为智慧树在线教育平台设计的Chrome浏…

阅读更多
Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案
2026/7/12 0:01:57

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否在GOG或Epic Games Store购买了心仪的游戏…

阅读更多
办公自动化实战:5个免费工具构建合同处理流水线
2026/7/12 0:01:57

办公自动化实战:5个免费工具构建合同处理流水线

1. 这不是“又一个工具包”,而是一套经过237次真实场景验证的效率组合拳“2026.04.28实用教程工具分享”这个标题乍看平平无奇,像极了你邮箱里被自动归入“促销/订阅”文件夹的那类通知——但如果你真把它当普通更新忽略,接下来半年里&#x…

阅读更多
基于Dify与DeepSeek构建私有知识库问答系统实战指南
2026/7/11 9:29:01

基于Dify与DeepSeek构建私有知识库问答系统实战指南

在业务中快速构建一个能理解私有文档、准确回答专业问题的智能助手,是很多开发团队面临的共同挑战。传统方案往往需要从零开始搭建复杂的 RAG(检索增强生成)系统,涉及文档解析、向量化、检索、大模型调用等多个环节,整…

阅读更多
FAE放射组学分析工具:医学影像特征探索的完整解决方案
2026/7/11 9:29:01

FAE放射组学分析工具:医学影像特征探索的完整解决方案

FAE放射组学分析工具:医学影像特征探索的完整解决方案 【免费下载链接】FAE FeAture Explorer 项目地址: https://gitcode.com/gh_mirrors/fae/FAE 你是否曾经面对海量医学影像数据感到无从下手?想要从CT、MRI等影像中提取有价值的定量特征&#…

阅读更多
DesktopNaotu:你的终极离线思维导图解决方案,告别网络依赖!
2026/7/11 9:29:01

DesktopNaotu:你的终极离线思维导图解决方案,告别网络依赖!

DesktopNaotu:你的终极离线思维导图解决方案,告别网络依赖! 【免费下载链接】DesktopNaotu 桌面版脑图 (百度脑图离线版,思维导图) 跨平台支持 Windows/Linux/Mac OS. (A cross-platform multilingual Mind Map Tool) 项目地址:…

阅读更多