HarmonyOS运动健康——身体数据与成就页面实现详解
个人中心的六个菜单入口中身体数据和我的成就是两个纯展示型页面。它们没有复杂的交互逻辑但在布局方式上有明显差异——身体数据是纵向列表成就页面是网格。这两个页面恰好代表了 ArkTS 里两种最常用的排列模式值得拆开看看各自的实现细节。完整效果BodyDataPage列表卡片的数据展示页面结构身体数据页面的视觉结构很简单顶部导航栏中间六个指标卡片纵向排列每个卡片占据一行。从截图看每张卡片左侧是指标名称小字灰色和数值大字彩色右侧是一个灰色的右箭头暗示可以点击进入编辑。整体布局用Scroll Column实现Scroll(){Column(){this.DataCard(体重,68.5,kg,A)this.DataCard(身高,175,cm,#5DADE2)this.DataCard(BMI,22.4,正常,#00B894)this.DataCard(体脂率,18.2,%,#FF9F43)this.DataCard(肌肉量,52.3,kg,#8A5DFA)this.DataCard(基础代谢,1680,千卡,#E8734A)Blank().height(20)}.width(100%).padding({left:16,right:16})}Scroll保证了内容超出屏幕时可以上下滑动Column里的六个DataCard依次纵向排列。最后的Blank().height(20)是底部留白防止最后一张卡片紧贴屏幕边缘。DataCard Builder 的拆解BuilderDataCard(label:string,value:string,unit:string,color:string){Row(){Column(){Text(label).fontSize(13).fontColor(T2)Row(){Text(value).fontSize(32).fontWeight(FontWeight.Bold).fontColor(color)Text( unit).fontSize(14).fontColor(T3)}.margin({top:4})}.alignItems(HorizontalAlign.Start).layoutWeight(1)SymbolGlyph($r(sys.symbol.chevron_right)).fontSize(14).fontColor([#DDD])}.width(100%).padding(18).backgroundColor(#FFFFFF).borderRadius(16).margin({bottom:10})}逐层分析这个 Builder 的布局嵌套最外层 Row横向排列layoutWeight(1)让左侧内容区占据所有剩余空间右侧的箭头图标被挤到最右边。中间 Column纵向排列标签和数值alignItems(HorizontalAlign.Start)让文字左对齐。数值行 Row把数值和单位放在同一行。数值用fontSize(32)的大号加粗字体单位用fontSize(14)的小号灰色字体。这个大小对比制造了数值为主、单位为辅的视觉层次。右侧箭头SymbolGlyph($r(sys.symbol.chevron_right))是系统自带的右箭头符号。用$r()引用系统符号资源而不是硬编码路径保证了在不同设备和系统版本上都能正确渲染。颜色编码的设计意图六个指标各有自己的颜色指标颜色色值体重红色#FF4757身高蓝色#5DADE2BMI绿色#00B894体脂率橙色#FF9F43肌肉量紫色#8A5DFA基础代谢珊瑚色#E8734A这不是随意配色。红色代表核心指标体重是最重要的身体数据蓝色代表基础属性身高不会变绿色代表健康状态BMI 正常是好事橙色代表需要关注体脂率偏高的话需要警惕紫色和珊瑚色分别对应肌肉和代谢和 App 的主色调体系保持一致。这种一个指标一个颜色的做法在数据展示页面里很常见。好处是用户扫一眼就能通过颜色定位到自己关心的指标不需要逐行阅读文字。坏处是如果指标太多超过 7-8 个颜色区分度会下降。目前 6 个指标正好在可区分的范围内。编辑按钮的占位右上角的红色编辑文字目前没有绑定任何点击事件。它是一个 UI 占位——告诉用户这里以后可以编辑身体数据但实际功能还没实现。这种先放占位后填逻辑的做法在 App 开发中很普遍。好处是用户能提前感知到页面的完整功能规划坏处是如果占位时间太长用户点了没反应会觉得 App 有 bug。在原型阶段可以接受上线前必须处理。AchievementPage网格布局的成就展示页面结构成就页面的视觉和身体数据完全不同——它是两列网格每个徽章占一个格子。从截图看8 个徽章排列成 4 行 2 列已获得的徽章有彩色标签未获得的被压暗。整体布局用Scroll Column Grid ForEach实现Scroll(){Column(){Grid(){ForEach(this.badges,(b:Badge){GridItem(){// 徽章内容}})}.columnsTemplate(1fr 1fr).columnsGap(10).rowsGap(10).width(100%).padding({left:16,right:16})Blank().height(20)}.width(100%)}Grid是 ArkTS 的网格布局组件columnsTemplate(1fr 1fr)定义了两列等宽布局。1fr是 fraction分数的缩写两个1fr表示把可用空间平分成两份。columnsGap(10)设置列间距为 10vprowsGap(10)设置行间距为 10vp。和身体数据页的Column纵向排列不同Grid天然支持多行多列不需要嵌套Row。这是选择Grid而不是Row Column组合的核心原因。Badge 接口与数据定义interfaceBadge{icon:stringname:stringdesc:stringearned:booleancolor:string}用interface定义徽章的数据结构。在 ArkTS 里interface和type都能用来定义对象类型但interface在 IDE 里的类型提示更完整——鼠标悬停时能看到每个字段的名称和类型而type有时只显示object。Statebadges:Badge[][{icon:,name:连续7天,desc:连续运动7天,earned:true,color:#FF4757},{icon:,name:百次训练,desc:完成100次训练,earned:true,color:#FF9F43},{icon:,name:马拉松,desc:累计跑步42公里,earned:true,color:#5DADE2},{icon:⚡,name:燃脂达人,desc:累计消耗10000千卡,earned:true,color:#FECA57},{icon:,name:30天挑战,desc:连续运动30天,earned:false,color:#8A5DFA},{icon:,name:年度冠军,desc:年度运动时长第一,earned:false,color:#E8734A},{icon:,name:力量之王,desc:完成500次力量训练,earned:false,color:#00B894},{icon:,name:社区之星,desc:获得1000个赞,earned:true,color:#6C5CE7},]8 个徽章其中 5 个已获得earned: true3 个未获得。color字段用于已获得徽章的标签背景色每个徽章有自己的主题色。GridItem 内部的条件渲染这是成就页面最核心的实现细节——根据earned布尔值渲染完全不同的 UIGridItem(){Column(){Text(b.icon).fontSize(36).margin({bottom:8}).opacity(b.earned?1:0.25)Text(b.name).fontSize(13).fontWeight(FontWeight.Bold).fontColor(b.earned?T1:T3)Text(b.desc).fontSize(10).fontColor(T3).margin({top:2})if(b.earned){Text(✓ 已获得).fontSize(9).fontColor(b.color).fontWeight(FontWeight.Bold).padding({left:8,right:8,top:2,bottom:2}).backgroundColor(b.color15).borderRadius(6).margin({top:6})}else{Row(){}.width(30).height(2).borderRadius(1).backgroundColor(#E0DCE8).margin({top:8})}}}三个关键的视觉差异图标透明度已获得的徽章图标opacity(1)正常显示未获得的opacity(0.25)几乎隐形。这让用户一眼就能区分哪些成就已经解锁。名称颜色已获得的用深色T1#1E1B2E未获得的用灰色T3#BBBBBB。颜色对比进一步强化了已完成 vs 未完成的区分。底部标签已获得的显示带颜色的✓ 已获得标签未获得的只放一个小灰色横条。这个横条的作用是占位——如果两个格子一个有标签一个没有底部会对不齐视觉上会显得参差不齐。加一个等高的横条保持了网格的整齐。已获得数量的动态计算privateearnedCount():number{letc:number0for(leti:number0;ithis.badges.length;i){if(this.badges[i].earned)c}returnc}右上角显示的5/8就是用这个方法计算的。遍历badges数组统计earned为true的数量。没有用filter().length的写法原因是 ArkTS 里Array.filter()返回的类型推断有时候不够精确IDE 会报类型警告。手动for循环虽然啰嗦一点但类型安全不会有问题。整卡片的透明度控制.width(100%).padding(14).backgroundColor(#FFFFFF).borderRadius(16).opacity(b.earned?1:0.6)除了图标和文字的单独透明度控制整个 GridItem 的容器也有透明度变化——未获得的卡片整体opacity(0.6)。这种双重透明度整体 局部制造了一种未解锁的视觉效果比单纯灰掉文字更自然。两个页面的布局对比身体数据页和成就页面在布局策略上的差异本质上是数据维度决定的维度身体数据页成就页面数据结构扁平列表每项独立网格矩阵每项等权信息密度一行一项信息量大一格一项信息量小排列方式纵向 Column二维 Grid交互暗示右箭头→可编辑无箭头→纯展示滚动方向纵向 Scroll纵向 Scroll内容可能横向扩展身体数据用列表是因为每个指标有标签 数值 单位三层信息需要水平空间来展开。成就用网格是因为每个徽章只有图标 名称两层信息正方形格子刚好够放。选错布局方式会导致视觉混乱。如果把身体数据塞进网格每格里挤三个字段会显得拥挤如果把成就排成列表一行一个徽章会浪费大量横向空间页面会变得很长。页面导航的统一性两个页面的导航栏结构完全一致Row(){Row(){SymbolGlyph($r(sys.symbol.chevron_left)).fontSize(20).fontColor([T1])}.width(34).height(34).borderRadius(17).backgroundColor(rgba(0,0,0,0.03)).justifyContent(FlexAlign.Center).onClick((){router.back()})Text(页面标题).fontSize(20).fontWeight(FontWeight.Bold).fontColor(T1).margin({left:10}).layoutWeight(1)// 右侧内容}34×34 的圆形返回按钮、rgba(0,0,0,0.03)的浅灰背景、20px 的系统左箭头。这个返回按钮的样式从运动记录页、训练页、饮食记录页一路沿用下来已经成为整个 App 的标准导航模式。唯一差异是右侧区域身体数据页放了红色编辑文字成就页面放了5/8计数。这种左侧固定、右侧灵活的设计让导航栏在保持一致性的同时能根据页面需求展示不同的辅助信息。数据目前是 Mock 的两个页面的数据目前都是写死在State里的 mock 数据。身体数据的六个指标值、成就的八个徽章都是硬编码的初始值。如果以后要接真实数据改造路径很清晰身体数据页从本地存储或服务器获取用户的身体指标替换State的初始值成就页面根据用户的运动数据计算哪些成就已解锁动态更新earned字段但在当前原型阶段mock 数据足够用来验证 UI 布局和视觉效果。先把界面做对再把数据接通——这是大多数 App 开发的实际节奏。

相关新闻

vLLM生产部署实战:GPU显存调度与OpenAI API兼容性全解析

vLLM生产部署实战:GPU显存调度与OpenAI API兼容性全解析

1. 这不是“搭个API”:为什么vLLM生产化部署是场系统工程我第一次在客户现场看到那个告警时,心里咯噔一下——线上推理服务的P99延迟突然从320ms飙到2.7秒,错误率翻了4倍。运维同事甩过来的日志里只有一行:“Request timeout: no …

2026/7/11 21:48:44 阅读更多 →
麒麟信安安全容器魔方架构深度解析:Controller、Agent与Registry三模块协同工作

麒麟信安安全容器魔方架构深度解析:Controller、Agent与Registry三模块协同工作

麒麟信安安全容器魔方架构深度解析:Controller、Agent与Registry三模块协同工作 【免费下载链接】ks-scmc KylinSec security Container magic Cube (Back-end), provides streamlined, efficient and secure containers and management. 项目地址: https://gitco…

2026/7/11 21:48:44 阅读更多 →
118、超分模型的可解释性:可视化注意力图与特征图分析

118、超分模型的可解释性:可视化注意力图与特征图分析

118、超分模型的可解释性:可视化注意力图与特征图分析 去年调一个EDSR的魔改模型,跑出来的结果在纹理区域总是糊成一团,峰值信噪比倒是挺高,但肉眼一看就知道不对劲。我盯着那些数字看了半天,最后决定把中间层的特征图拉出来看看——这才发现模型在高层特征里压根没关注到…

2026/7/11 21:46:42 阅读更多 →

最新新闻

RT-Thread 软件定时器原理深度解析:从链表到跳表,如何管理1000+定时器

RT-Thread 软件定时器原理深度解析:从链表到跳表,如何管理1000+定时器

RT-Thread软件定时器内核机制解析:跳表算法如何实现高效管理1. 软件定时器的核心价值与应用场景在嵌入式实时系统中,定时器如同系统的心跳节拍器,驱动着各类周期性任务的执行。RT-Thread作为一款开源嵌入式实时操作系统,其软件定时…

2026/7/11 23:31:03 阅读更多 →
ArcGIS 10.8 与 Python 3.8 环境共存:2步配置解决模块冲突

ArcGIS 10.8 与 Python 3.8 环境共存:2步配置解决模块冲突

ArcGIS 10.8 与 Python 3.8 环境共存:2步配置解决模块冲突当数据分析师或开发者需要在同一台机器上同时运行ArcGIS 10.8和Python 3.8时,环境冲突问题常常让人头疼。ArcGIS 10.8内置的是Python 2.7环境,而现代数据分析工作流往往依赖Python 3.…

2026/7/11 23:31:03 阅读更多 →
AI 护栏(Guardrails)彻底讲透:为什么你的大模型上线就翻车,以及如何用一套防呆机制让 AI 真正可用?

AI 护栏(Guardrails)彻底讲透:为什么你的大模型上线就翻车,以及如何用一套防呆机制让 AI 真正可用?

大模型 demo 阶段总是惊艳,一旦上线到生产环境就会频繁"翻车":答非所问、生成违规内容、调用了不该调用的接口、把用户隐私写进了日志…… 这些问题的根源不是模型不够强,而是你缺了一套"防呆机制"——也就是 AI 护栏&am…

2026/7/11 23:27:03 阅读更多 →
STM32与G6D-ASI继电器在直流负载管理的优化实践

STM32与G6D-ASI继电器在直流负载管理的优化实践

1. 项目背景与核心目标在工业自动化与电力电子领域,直流负载管理一直是系统设计的关键痛点。传统方案普遍存在两个主要问题:一是机械式继电器的触点寿命有限,在频繁切换场景下容易失效;二是控制逻辑简单,无法根据负载特…

2026/7/11 23:27:03 阅读更多 →
好用的区域教育一体化管理平台哪个更全面

好用的区域教育一体化管理平台哪个更全面

在当今信息化时代,教育行业的数字化转型已经成为大势所趋。一个好的区域教育一体化管理平台不仅能够提升教育管理效率,还能为教师和学生提供更好的教学体验。那么,在众多的教育管理平台中,哪一个更全面呢?本文将从功能…

2026/7/11 23:25:02 阅读更多 →
靠谱的区域教育一体化管理平台哪个更专业

靠谱的区域教育一体化管理平台哪个更专业

在当今数字化转型的大背景下,教育行业也迎来了前所未有的变革。如何实现教育局与学校之间的高效协同,提升管理水平,成为许多教育管理者关注的重点。面对市场上众多的教育管理平台,选择一个既专业又可靠的一体化管理平台显得尤为重…

2026/7/11 23:25:02 阅读更多 →

日新闻

5分钟完全掌握:ComfyUI ControlNet预处理器终极使用指南

5分钟完全掌握:ComfyUI ControlNet预处理器终极使用指南

5分钟完全掌握:ComfyUI ControlNet预处理器终极使用指南 【免费下载链接】comfyui_controlnet_aux ComfyUIs ControlNet Auxiliary Preprocessors 项目地址: https://gitcode.com/gh_mirrors/co/comfyui_controlnet_aux 想要让AI图像生成真正听从你的指挥吗&…

2026/7/11 0:02:12 阅读更多 →
PIC18F45K42驱动EPT-14A4005P压电蜂鸣器方案详解

PIC18F45K42驱动EPT-14A4005P压电蜂鸣器方案详解

1. 项目背景与核心需求 在工业控制、安防系统和智能家居等领域,可靠的声音警报系统是不可或缺的基础组件。传统蜂鸣器存在音量不足、音质模糊等问题,而基于压电陶瓷技术的EPT-14A4005P蜂鸣器配合PIC18F45K42微控制器,能够构建一套适应性强、音…

2026/7/11 0:04:12 阅读更多 →
大模型推理中的算子融合优化:LayerNorm + Attention 的 CUDA Kernel 手写与验证

大模型推理中的算子融合优化:LayerNorm + Attention 的 CUDA Kernel 手写与验证

大模型推理中的算子融合优化:LayerNorm Attention 的 CUDA Kernel 手写与验证 一、GPU 利用率 30%:分开的算子吃掉所有带宽 推理服务的 GPU 利用率监测显示一个反直觉的现象:计算核心(SM)利用率不到 30%,但…

2026/7/11 0:04:12 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/11 22:54:57 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/9 13:46:46 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/11 19:55:29 阅读更多 →

月新闻