HarmonyOS ArkTS 实战:实现一个精准秒表应用
HarmonyOS ArkTS 实战实现一个精准秒表应用项目效果本文实现的是一个基于 HarmonyOS 和 ArkTS 的精准秒表应用。项目中使用 ArkUI 组件完成页面布局通过State管理状态数据实现开始/暂停/重置计时、计次功能、计次记录列表、毫秒级精度显示和大字体时间显示等功能。最终运行效果如下页面主要包含以下内容顶部应用标题大字体时间显示分:秒.毫秒开始/暂停按钮计次/重置按钮计次记录列表计次序号、分段时间和总时间空状态提示页面整体采用 ArkUI 声明式布局。本文重点是演示如何在 HarmonyOS 项目中使用 ArkTS 和 ArkUI 实现一个精准计时类单页面应用。项目代码主要写在entry/src/main/ets/pages/Index.ets文件中适合作为 HarmonyOS ArkTS 入门到进阶之间的练习案例。前言秒表是生活中常用的计时工具无论是运动计时、实验记录还是游戏测速都需要一个精准易用的秒表。手机自带的秒表往往功能简单而我们可以自己实现一个功能完整、界面美观的秒表应用。从应用开发角度来看这个项目不依赖后端接口也不需要数据库但能练习 ArkTS 中的状态管理、高精度定时器、时间格式化、列表渲染和按钮交互等内容。本文基于 HarmonyOS 和 ArkTS 实现一个精准秒表应用。用户可以开始、暂停和重置计时记录计次分段时间查看每次计次的详细数据。这个项目的核心不是简单的数字累加而是精准的时间控制和计次功能。每一次开始、暂停、计次和重置本质上都是对计时器状态的管理。状态变化后页面会自动刷新这正是 ArkUI 声明式开发的基本思想。一、项目目标本次实践主要实现以下目标创建 HarmonyOS ArkTS 页面使用Entry和Component定义页面组件使用State管理页面状态使用高精度定时器实现毫秒级计时实现开始/暂停功能实现重置功能实现计次功能格式化时间显示分:秒.毫秒记录每次计次的分段时间记录每次计次的总时间使用List和ForEach渲染计次记录使用空状态提示优化无计次页面使用Builder封装按钮和计次项完成一个可以运行的秒表页面。这个项目虽然是单页面应用但它有完整的计时控制、计次记录和时间显示功能比普通静态页面更适合练习 ArkTS。二、技术栈类型内容开发方向HarmonyOS 应用开发开发语言ArkTSUI 框架ArkUISDK 版本HarmonyOS API 23 及以上工程模型Stage 模型核心组件Text / Button / Column / Row / List / ForEach状态管理State数据处理时间计算 / 高精度计时 / 数组操作项目入口entry/src/main/ets/pages/Index.ets运行平台模拟器或真机本项目是 HarmonyOS 原生 ArkTS 项目。页面主体由 ArkUI 组件构建核心逻辑写在Index.ets文件中不依赖后端接口也不需要额外配置数据库。三、为什么选择秒表项目精准秒表应用适合作为 ArkTS 练习项目主要有以下几个原因。第一实用性强。秒表是非常经典的工具类应用在很多场景下都会用到。第二业务场景真实。运动、实验、游戏等场景都需要计时功能是手机必备工具之一。第三适合练习状态管理。运行状态、经过时间、开始时间、计次记录都属于页面状态。状态变化后页面会自动刷新。第四适合练习定时器使用。高精度计时需要使用定时器这是前端开发中重要的基础技能。第五适合练习时间格式化。将毫秒数格式化为易读的分秒毫秒格式是常见的开发需求。第六扩展空间比较大。基础功能完成后可以继续增加倒计时、倒计时秒表切换、计时分享、本地保存记录和多组计时功能。在本项目中计时器状态和计次记录是核心数据。页面中的时间显示和计次列表都由它们计算或渲染得到。四、功能规则说明计时精度10毫秒0.01秒更新频率100次/秒。按钮状态规则当前状态主按钮副按钮初始状态开始重置禁用运行中暂停计次暂停中开始重置计次规则点击计次按钮记录当前时间点分段时间 当前总时间 - 上一次计次总时间计次按倒序显示最新的在最上面最多记录99次计次时间显示格式MM:SS.cc例如01:23.45表示1分23秒45。五、项目结构本项目主要修改首页文件entry └── src └── main └── ets └── pages └── Index.ets其中文件作用Index.ets编写页面结构、状态数据和秒表计时逻辑本文不涉及复杂路由也不需要额外创建多个页面。对于练习项目来说把主要逻辑集中在一个Index.ets文件中更方便理解。如果后续继续扩展可以考虑把时间显示组件、控制按钮和计次项拆分成独立组件。六、核心实现思路本项目的核心流程如下定义计次记录数据结构使用State保存运行状态、经过时间、定时器ID和计次记录点击开始按钮启动定时器每10毫秒更新一次经过时间点击暂停按钮停止定时器点击计次按钮记录当前时间计算分段时间和总时间点击重置按钮清空所有数据格式化时间显示为易读格式使用ForEach渲染计次记录列表根据当前状态动态改变按钮文字和功能没有计次时显示空状态提示。项目中最重要的状态变量如下State isRunning: boolean false State elapsedTime: number 0 State timerId: number -1 State lastLapTime: number 0 State laps: LapRecord[] [] State nextLapNumber: number 1其中状态变量作用isRunning计时器是否运行中elapsedTime经过的总时间毫秒timerId定时器IDlastLapTime上一次计次的时间laps计次记录数组nextLapNumber下一个计次的序号elapsedTime和laps是本项目中最重要的数据。时间显示和计次列表都依赖这两个状态。七、Index.ets 完整代码打开文件entry/src/main/ets/pages/Index.ets将其中内容替换为下面代码interfaceLapRecord{number:numbersplitTime:numbertotalTime:number}EntryComponentstruct Index{StateisRunning:booleanfalseStateelapsedTime:number0StatetimerId:number-1StatelastLapTime:number0StatenextLapNumber:number1Statelaps:LapRecord[][]privatestartTime:number0aboutToDisappear(){this.stopTimer()}privatestartTimer():void{if(this.isRunning)returnthis.isRunningtruethis.startTimeDate.now()-this.elapsedTimethis.timerIdsetInterval((){this.elapsedTimeDate.now()-this.startTime},10)}privatepauseTimer():void{if(!this.isRunning)returnthis.isRunningfalsethis.stopTimer()}privatestopTimer():void{if(this.timerId!-1){clearInterval(this.timerId)this.timerId-1}}privateresetTimer():void{this.pauseTimer()this.elapsedTime0this.lastLapTime0this.nextLapNumber1this.laps[]}privaterecordLap():void{if(!this.isRunning)returnif(this.laps.length99)returnletsplitTimethis.elapsedTime-this.lastLapTimeletlap:LapRecord{number:this.nextLapNumber,splitTime:splitTime,totalTime:this.elapsedTime}this.laps[lap,...this.laps]this.lastLapTimethis.elapsedTimethis.nextLapNumber}privateformatTime(ms:number):string{letminutesMath.floor(ms/60000)letsecondsMath.floor((ms%60000)/1000)letcentisecondsMath.floor((ms%1000)/10)return${this.formatTwo(minutes)}:${this.formatTwo(seconds)}.${this.formatTwo(centiseconds)}}privateformatTwo(value:number):string{returnvalue10?0value.toString():value.toString()}privategetFastestLap():number{if(this.laps.length2)return-1letminTimeMath.min(...this.laps.map(ll.splitTime))returnthis.laps.find(ll.splitTimeminTime)?.number||-1}privategetSlowestLap():number{if(this.laps.length2)return-1letmaxTimeMath.max(...this.laps.map(ll.splitTime))returnthis.laps.find(ll.splitTimemaxTime)?.number||-1}BuilderControlButton(text:string,color:string,bgColor:string,onClick:()void){Button(text).width(80).height(80).fontSize(18).fontColor(color).backgroundColor(bgColor).borderRadius(40).onClick(onClick)}BuilderLapItem(lap:LapRecord){letfastestthis.getFastestLap()letslowestthis.getSlowestLap()lettextColor#182431if(lap.numberfastest){textColor#10B981}elseif(lap.numberslowest){textColor#EF4444}Row(){Text(计次${lap.number}).fontSize(15).fontColor(#6B7280).width(80)Text(this.formatTime(lap.splitTime)).fontSize(16).fontWeight(FontWeight.Medium).fontColor(textColor).layoutWeight(1).textAlign(TextAlign.Center)Text(this.formatTime(lap.totalTime)).fontSize(16).fontColor(#182431).width(100).textAlign(TextAlign.End)}.width(100%).padding(16).margin({bottom:1}).backgroundColor(Color.White)}build(){Column(){Text(秒表).fontSize(28).fontWeight(FontWeight.Bold).fontColor(#182431).margin({top:22})Text(基于 HarmonyOS ArkTS 的精准计时工具).fontSize(14).fontColor(#6B7280).margin({top:8,bottom:40})Text(this.formatTime(this.elapsedTime)).fontSize(72).fontWeight(FontWeight.Bold).fontColor(#182431).fontFamily(monospace).textAlign(TextAlign.Center).margin({bottom:60})Row(){if(this.isRunning){this.ControlButton(计次,#0A59F7,#EFF6FF,(){this.recordLap()})}else{this.ControlButton(重置,this.elapsedTime0?#EF4444:#9CA3AF,this.elapsedTime0?#FEF2F2:#F3F4F6,(){this.resetTimer()})}Blank()if(this.isRunning){this.ControlButton(暂停,#F59E0B,#FEF3C7,(){this.pauseTimer()})}else{this.ControlButton(开始,#10B981,#D1FAE5,(){this.startTimer()})}}.width(100%).padding({left:30,right:30}).margin({bottom:30})if(this.laps.length0){Row(){Text(计次).fontSize(13).fontColor(#9CA3AF).width(80)Text(分段时间).fontSize(13).fontColor(#9CA3AF).layoutWeight(1).textAlign(TextAlign.Center)Text(总时间).fontSize(13).fontColor(#9CA3AF).width(100).textAlign(TextAlign.End)}.width(100%).padding({left:16,right:16,top:12,bottom:12}).backgroundColor(#F9FAFB)}if(this.laps.length0){Column(){Text(暂无计次记录).fontSize(16).fontColor(#6B7280)Text(开始计时后点击计次按钮记录分段时间).fontSize(13).fontColor(#9CA3AF).margin({top:8})}.width(100%).padding(30).backgroundColor(Color.White).borderRadius(16)}else{List(){ForEach(this.laps,(lap:LapRecord){ListItem(){this.LapItem(lap)}},(lap:LapRecord)lap.number.toString())}.width(100%).layoutWeight(1).scrollBar(BarState.Off).borderRadius(16).clip(true)}}.width(100%).height(100%).padding({left:18,right:18}).backgroundColor(#F5F7FA)}}八、代码实现说明1. 高精度计时使用Date.now()获取时间戳计算经过的时间而不是简单累加这样可以避免定时器误差累积this.startTimeDate.now()-this.elapsedTimethis.timerIdsetInterval((){this.elapsedTimeDate.now()-this.startTime},10)每10毫秒更新一次实现10毫秒精度。2. 时间格式化将毫秒数格式化为MM:SS.cc格式privateformatTime(ms:number):string{letminutesMath.floor(ms/60000)letsecondsMath.floor((ms%60000)/1000)letcentisecondsMath.floor((ms%1000)/10)return${this.formatTwo(minutes)}:${this.formatTwo(seconds)}.${this.formatTwo(centiseconds)}}3. 按钮状态管理根据当前运行状态动态改变按钮的文字、颜色和功能未运行且时间为0开始/重置禁用运行中暂停/计次暂停中开始/重置4. 计次功能记录每次计次的分段时间和总时间最快计次显示绿色最慢计次显示红色letsplitTimethis.elapsedTime-this.lastLapTimeletlap:LapRecord{number:this.nextLapNumber,splitTime:splitTime,totalTime:this.elapsedTime}5. 定时器清理页面销毁时清除定时器避免内存泄漏aboutToDisappear(){this.stopTimer()}九、运行项目代码编写完成后在DevEco Studio中运行项目。测试开始/暂停/重置、计次功能检查时间显示是否准确计次记录是否正确。十、开发中遇到的问题定时器误差问题使用时间戳计算而不是累加避免误差累积按钮状态切换根据不同状态显示不同按钮最快最慢计次标记自动识别并高亮显示等宽字体使用monospace字体让数字对齐更美观十一、总结本文基于HarmonyOS和ArkTS实现了一个精准秒表应用。项目通过State管理计时状态使用高精度定时器实现毫秒级计时实现了开始/暂停/重置、计次记录和时间格式化等功能。这个项目展示了ArkTS中定时器使用、时间计算和状态管理的基本方法适合作为入门练习项目。

相关新闻

Parakeet MLX高级技巧:如何通过Beam解码与句子分割配置提升转录准确率

Parakeet MLX高级技巧:如何通过Beam解码与句子分割配置提升转录准确率

Parakeet MLX高级技巧:如何通过Beam解码与句子分割配置提升转录准确率 【免费下载链接】parakeet-mlx An implementation of the Nvidias Parakeet models for Apple Silicon using MLX. 项目地址: https://gitcode.com/gh_mirrors/pa/parakeet-mlx Parakeet…

2026/7/26 20:49:43阅读更多 →
【计算机Python毕业设计案例】基于用户画像与协同过滤的商品推荐系统 基于 Python 的电商行为数据分析与智能商品推送系统实现(程序+文档+讲解+定制)

【计算机Python毕业设计案例】基于用户画像与协同过滤的商品推荐系统 基于 Python 的电商行为数据分析与智能商品推送系统实现(程序+文档+讲解+定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/26 20:49:43阅读更多 →
如何用scikit-uplift实现精准营销:提升模型完整指南

如何用scikit-uplift实现精准营销:提升模型完整指南

如何用scikit-uplift实现精准营销:提升模型完整指南 【免费下载链接】scikit-uplift :exclamation: uplift modeling in scikit-learn style in python :snake: 项目地址: https://gitcode.com/gh_mirrors/sc/scikit-uplift 想要知道哪些客户会因为你的营销活…

2026/7/26 20:49:43阅读更多 →
计算机视觉中的图像增强技术与目标检测优化实践

计算机视觉中的图像增强技术与目标检测优化实践

1. 项目概述:当计算机视觉遇上图像预处理在计算机视觉的实际工程中,我们常常会遇到这样的困境:原始图像质量不佳导致目标检测准确率波动大。这个问题在我参与工业质检项目时尤为明显——产线摄像头拍摄的金属部件表面存在反光、噪点和运动模糊…

2026/7/26 22:19:59阅读更多 →
HarmonyOS开发实战:笔友-应用发布 Checklist——签名、隐私政策、权限声明、上架审核要点

HarmonyOS开发实战:笔友-应用发布 Checklist——签名、隐私政策、权限声明、上架审核要点

前言 在 HarmonyOS 应用开发完成后,应用发布是最后一步也是最关键的一步。从签名配置到隐私政策,从权限声明到上架审核,每个环节都可能成为"卡点"。 本文将以 xiexin 的 build-profile.json5、module.json5、AppScope/app.json5 …

2026/7/26 22:19:59阅读更多 →
C++网络聊天室实战:从Socket到epoll,掌握高并发服务器核心架构

C++网络聊天室实战:从Socket到epoll,掌握高并发服务器核心架构

1. 项目概述与核心价值最近在整理一些老项目,翻到了当年用C手搓网络聊天室的代码,感慨良多。这玩意儿可以说是每个C后端开发者的“成人礼”,它不像写个“Hello World”那么简单,也不像构建一个大型分布式系统那样复杂到让人望而却…

2026/7/26 22:19:59阅读更多 →
【前端性能】高性能滚动 scroll 及页面渲染优化

【前端性能】高性能滚动 scroll 及页面渲染优化

【前端性能】高性能滚动 scroll 及页面渲染优化 1. 为什么滚动性能如此重要?在现代 Web 应用中,滚动是最常见的用户交互之一。无论是长列表、无限加载、固定导航栏还是视差滚动,滚动性能直接影响用户体验。如果滚动时页面出现卡顿、掉帧&…

2026/7/26 22:19:59阅读更多 →
Python深度学习实战:YOLOv5智能宠物识别系统

Python深度学习实战:YOLOv5智能宠物识别系统

1. 项目概述:当Python遇上深度学习打造智能宠物识别去年帮学弟调试毕业设计时,发现市面上大多数宠物识别项目还停留在简单的轮廓匹配阶段。这激发了我用YOLOv5重构整个系统的想法——通过迁移学习在ResNet50 backbone上微调,最终在测试集上达…

2026/7/26 22:19:59阅读更多 →
多模态MRI重建:深度学习与物理模型融合的创新方案

多模态MRI重建:深度学习与物理模型融合的创新方案

1. 多模态MRI重建的技术挑战与现状磁共振成像(MRI)作为一种非侵入式的医学影像技术,其重建质量直接影响临床诊断的准确性。传统MRI扫描面临两个核心痛点:扫描时间长带来的患者不适,以及多模态数据(如T1、T2…

2026/7/26 22:17:58阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/26 0:01:28阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/26 0:01:28阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/26 0:01:28阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/26 0:01:28阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/26 0:01:28阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/26 0:01:28阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/25 23:03:25阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/26 19:05:21阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/26 19:05:21阅读更多 →