# 鸿蒙 HarmonyOS 应用开发实战(第33期)|喝水提醒(Water Reminder)— 可视化水杯与进度动画
一、应用概述喝水提醒Water Reminder是一款健康辅助类应用帮助用户记录每日饮水量并以可视化水杯的形式直观展示饮水进度。用户每点击一次「喝一杯」按钮水杯中的水位就会上升一格同时显示累计饮水量毫升和鼓励性文字提示。从健康角度看每日饮用 8 杯水约 2000ml是广为流传的健康建议。该应用以此为目标通过视觉反馈和正向鼓励两个心理机制激励用户达成每日饮水目标。从技术角度看这是一个展示Stack 层叠中动态高度变化、条件文字渲染和响应式布局的绝佳案例。二、技术架构与组件树2.1 整体架构Entry Component struct index33 ├── Column (根容器) │ ├── Row (顶部导航栏) │ └── Column (主内容区, 居中) │ ├── Text (目标: 8 杯) │ ├── Stack (水杯可视化) │ │ ├── Column (水杯容器, 180×200, 圆角边框) │ │ │ └── Column (水位填充, 动态高度) │ │ └── Column (水杯文字叠加层) │ │ ├── Text () │ │ └── Text ({count}/{target}) │ ├── Text ({totalMl}ml / {target*glassSize}ml) │ ├── Text (鼓励语, 条件变化) │ ├── Button ( 喝一杯) │ └── Row (辅助按钮) │ ├── Button (重置) │ └── Button (目标)2.2 状态变量设计State count: number 0; // 已饮杯数 State target: number 8; // 日目标杯数 State glassSize: number 200; // 每杯毫升数三个State变量构成了应用的全部状态。其中glassSize被标记为State虽然当前未通过 UI 修改它但保留为状态变量意味着未来可以轻松添加用户自定义杯量功能。三、核心代码深度解析3.1 喝水逻辑与边界保护addWater() { if (this.count this.target) { this.count; } }addWater()方法包含明确的边界检查只有当前杯数小于目标杯数时才递增。这防止了用户过度点击导致进度超过 100% 的异常情况。当count target时点击按钮不再产生任何效果——这是一种软锁止设计比禁用按钮更温和用户仍然可以感受到点击反馈。3.2 计算属性进度、水量与鼓励语get progress(): number { return (this.count / this.target) * 100; } get totalMl(): number { return this.count * this.glassSize; } get encouragement(): string { if (this.count this.target) return 达标了很棒; if (this.count this.target * 0.75) return 快达标了; if (this.count this.target * 0.5) return 继续加油; if (this.count this.target * 0.25) return 多喝点水; return 记得喝水; }三个计算属性将原始数据count、target转化为用户友好的显示信息progress以百分比形式返回进度值可用于替代传统的环形进度条totalMl根据杯数和杯量计算总毫升数encouragement基于不同进度区间返回不同的鼓励文字配合对应的 emoji 表情鼓励语的区间设计合理在 0%、25%、50%、75%、100% 五个关键节点切换文字避免了过于频繁的变化也让用户在每个进步阶段都能获得正向反馈。3.3 水杯可视化——Stack 层叠的核心Stack() { // 水杯背景和动态水位 Column() { Text().width(160) .height(this.count 0 ? 160 * (this.count / this.target) : 0) .backgroundColor(#4FC3F7) .borderRadius({ bottomLeft: 20, bottomRight: 20 }) .alignSelf(ItemAlign.Center) } .width(180).height(200).backgroundColor(#E1F5FE) .borderRadius(20).justifyContent(FlexAlign.End) .border({ width: 3, color: #81D4FA }) // 水杯上的文字叠加 Column() { Text().fontSize(24) Text(${this.count}/${this.target}).fontSize(16) .fontWeight(FontWeight.Bold).fontColor(#0277BD) } .width(100%).height(100%) .justifyContent(FlexAlign.Center) .alignItems(HorizontalAlign.Center) }水杯渲染的核心逻辑分为两层第一层杯体 水位外层 Column 代表整个水杯180×200使用#E1F5FE极浅蓝色作为空杯颜色borderRadius(20)创建圆角杯体border添加 3px 的边框模拟玻璃质感。内层 Column 代表水位它的height根据count/target比例动态计算160 * (this.count / this.target)。当count 0时高度为 0——水杯看起来是空的。这里有一个重要的布局细节外层 Column 设置了justifyContent(FlexAlign.End)这意味着内层水位 Column 会从底部开始排列。结合alignSelf(ItemAlign.Center)让水位水平居中水的填充效果就是从杯底逐渐上升到杯顶——完美模拟了真实倒水的视觉效果。borderRadius({ bottomLeft: 20, bottomRight: 20 })为水位底部添加圆角与水杯的底部圆角匹配。水位顶部是平的这与真实透明玻璃杯中水的视觉效果一致。第二层文字叠加第二个 Column 使用position叠加在水杯之上Stack 的特性显示 表情和count/target计数。justifyContent(Center)和alignItems(Center)确保文字在杯体中央显示。3.4 激励按钮与辅助操作Button( 喝一杯).width(200).height(56).borderRadius(28) .backgroundColor(#4FC3F7).fontSize(22).margin({ top: 12 }) .onClick(() this.addWater()) Row({ space: 8 }) { Button(重置).width(90).height(40).borderRadius(20) .backgroundColor(#9E9E9E) .onClick(() { this.count 0 }) Button(目标).width(90).height(40).borderRadius(20) .backgroundColor(#FF9800) .onClick(() { this.target }) }.margin({ top: 8 })三个按钮的设计体现了清晰的信息层级主按钮「 喝一杯」最大的尺寸200×56最醒目的颜色蓝色系是用户最频繁的操作次按钮「重置」中等大小灰色用于重置杯数次按钮「目标」橙色用于增加每日目标「目标」按钮允许用户灵活调整目标——如果某天想多喝水可以增加目标杯数。但需要注意的是当前版本没有「目标-」按钮这可以作为一个改进点。四、HarmonyOS 特性分析4.1 动态高度的响应式渲染本例最值得关注的技术点是基于State的动态高度变化。当count递增时.height(this.count 0 ? 160 * (this.count / this.target) : 0)ArkTS 的响应式系统会自动重新计算高度值并重新渲染。这种数据驱动高度的模式适用于进度条/进度环可伸缩面板加载动画数据可视化的柱状图4.2 borderRadius 的精细控制.borderRadius({ bottomLeft: 20, bottomRight: 20 })ArkTS 的borderRadius支持对象参数可以对四个角分别设置圆角值。这是 CSS 中border-radius的增强版本比传统的四值简写更直观。4.3 语义化颜色系统应用使用了统一的蓝色系配色背景#E1F5FE极浅蓝水位#4FC3F7中蓝与主按钮一致边框#81D4FA浅蓝文字#0277BD深蓝这种单色系设计让视觉风格高度统一用户看到蓝色系就能联想到水的主题。在 HarmonyOS 中颜色值支持六位十六进制#RRGGBB或八位#AARRGGBB格式。五、UI/UX 设计与最佳实践5.1 视觉反馈的心理学应用应用的核心理念是通过即时视觉反馈激励用户行为水位上升的满足感每次点击蓝色水位都会增高这种可视化的进步给人成就感计数实时更新水杯中央的count/target数字实时变化鼓励语的阶段性变化从「记得喝水」到「达标了很棒」五种文字对应五个进步阶段5.2 交互反馈的细节按钮溢出保护当达到目标后点击主按钮无效而不是报错温和的视觉风格圆角按钮、柔和的蓝色系、大号字体给人友好的感觉重置安全重置仅清空杯数count不影响目标target和杯量glassSize避免用户误操作导致所有设置丢失5.3 无障碍设计建议对于喝水提醒这类高频使用的健康应用建议增加系统通知提醒通过ohos.notification定时发送喝水通知振动反馈每次喝水时提供短暂振动语音播报鼓励语通过 TTS 语音读出来六、可扩展思路历史记录与统计使用ohos.data.preferences持久化每日饮水数据显示周/月趋势图。自定义杯量允许用户设置不同的杯量如 250ml、300ml适配不同水杯。定时提醒利用后台任务定时发送喝水通知每隔 1-2 小时提醒一次。多主题支持不同的水杯样式和背景主题增加趣味性。喝水挑战加入连续达标天数的统计用游戏化方式激励用户。七、总结喝水提醒应用以 83 行简洁代码实现了一个完整的健康追踪工具。它的核心价值在于Stack 层叠实现复杂视觉水杯 水位 文字的叠加展示了 Stack 在可视化组件中的强大能力动态高度驱动进度显示用State控制 Column 高度替代了传统的 Progress 组件计算属性简化业务逻辑progress、totalMl、encouragement三个 getter 将原始数据转化为展示信息正向激励设计通过鼓励语和可视化进度利用心理学原理帮助用户养成好习惯这个应用的代码模式——状态驱动的动态尺寸变化 层叠布局的可视化——可以轻松复用到电池电量显示、存储空间指示器、技能升级条等场景。下一期我们将继续健康主题探讨一个更具互动性的应用——计步器Pedometer学习如何使用Progress的环形样式和Ring类型打造精美的运动数据看板。本文是 HarmonyOS 应用开发实战系列第 33 期更多内容请关注专栏。

相关新闻

Spring Boot集成Google Authenticator实现两步验证:从原理到实战

Spring Boot集成Google Authenticator实现两步验证:从原理到实战

1. 项目概述:为什么你的Spring Boot应用需要两步验证?最近在给一个内部管理系统做安全加固,客户提了个很实在的要求:登录时除了密码,能不能再加一道锁?这个需求背后,是大家对账号安全越来越高的…

2026/9/29 19:49:19 阅读更多 →
AI编程助手如何提升开发效率:实践与量化分析

AI编程助手如何提升开发效率:实践与量化分析

1. 智能编码革命的技术本质当我在2022年首次使用GitHub Copilot完成一个完整的微服务模块时,那种震撼感至今难忘——原本需要3天编写的CRUD接口,在AI辅助下仅用4小时就完成了初版。这不仅仅是效率的提升,更标志着软件开发范式正在发生根本性变…

2026/10/14 8:21:46 阅读更多 →
AI 赋能行业的趋势预判:哪些传统业务场景将在下半年迎来爆发式智能化

AI 赋能行业的趋势预判:哪些传统业务场景将在下半年迎来爆发式智能化

AI 赋能行业的趋势预判:哪些传统业务场景将在下半年迎来爆发式智能化 一、行业智能化的"渗透率阶梯":从技术可行到商业可行 AI 赋能传统行业不是"所有行业同步进行",而是沿着一条清晰的"渗透率阶梯"逐步推进…

2026/10/14 4:45:17 阅读更多 →

最新新闻

GitHub Trending 榜单的深度解码:从星标数到技术趋势研判

GitHub Trending 榜单的深度解码:从星标数到技术趋势研判

1. 这不是榜单,而是一份开源生态的“实时心电图”你点开 GitHub Daily Top 10,看到的绝不止是十个仓库名和星标数。它是一张动态刷新的开源生态“心电图”——每一次 Star 的跃升、Fork 的扩散、Issue 的激增,都在同步传导着全球开发者真实的…

2026/10/15 22:28:47 阅读更多 →
C++与Node.js集成实战:原生模块构建、异步与内存安全指南

C++与Node.js集成实战:原生模块构建、异步与内存安全指南

如果你在Node.js项目里碰到CPU密集计算把进程拖到卡死,或者在数据编解码、图像处理这些环节上觉得纯JS的极限就摆在那里,那早晚会走到C与Node.js集成这条路上。我最早接触这块是被一个真实需求逼的:一个长时间运行的图像处理服务,…

2026/10/15 22:28:47 阅读更多 →
AI智能体如何用图纸识别与拆单技术重构全屋定制生产流程

AI智能体如何用图纸识别与拆单技术重构全屋定制生产流程

从门店接单到工厂出货,中间藏着全屋定制行业最磨人的环节:反复改图、人工拆单。这套流程慢、容易出错、还极度依赖熟练工——设计师熬夜改一版图纸,工厂拆单员又要对着图重新过一遍,客户等得急,工厂也等不起。AI智能体…

2026/10/15 22:28:47 阅读更多 →
C++与Node.js集成实战:N-API原生模块开发与异步性能优化

C++与Node.js集成实战:N-API原生模块开发与异步性能优化

1. 集成路线怎么选:先搞清楚三种玩法再动手C 与 Node.js 集成,我这边接触到的实际需求无非三种:第一是 CPU 密集型的计算逻辑想搬进 Node 里跑,比如图像处理、音视频编解码、加密解密、数值模拟;第二是公司积累了多年的…

2026/10/15 22:28:47 阅读更多 →
C++职责链模式实战:从if-else到优雅解耦

C++职责链模式实战:从if-else到优雅解耦

写C的职责链模式之前,我先说说自己是怎么掉进这个坑里的。当时在某跨平台消息中间件项目里处理收包逻辑,数据包要根据类型走不同分支:日志类的要落盘,业务类的要转发,异常类的要触发告警……用if-else硬写第一版还能凑…

2026/10/15 22:28:47 阅读更多 →
SpringBoot+Vue党员教育管理系统设计与实现:从需求分析到部署排坑

SpringBoot+Vue党员教育管理系统设计与实现:从需求分析到部署排坑

最近刚把一个计算机毕业设计项目完整跑通,用的是 SpringBoot Vue 的组合,题目是“党员教育和管理系统”,也可以理解成一套党校线上指导平台。如果你正好在选毕业设计题目,或者公司内部需要做一套线上学习培训系统,这个…

2026/10/15 22:27:31 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →