【HarmonyOS 6】HarmonyOS 自定义时间选择器实现
前言在开发时间管理类应用时时间选择器是一个非常常见的功能。本文将通过近期在鸿蒙应用开发中的一个实际案例详细讲解如何在 HarmonyOS 应用中实现一个自定义的时间选择器。我们这个案例中的选择器支持半小时为单位的时间选择适合用于记录时间块等场景。应用场景在本应用中用户需要记录已经完成的时间块。当用户点击记录时间按钮时会弹出一个对话框让用户选择开始时间和结束时间。注时间选择器支持小时和分钟的独立选择分钟只能选择 00 或 30核心知识点1. CustomDialog 自定义对话框在 HarmonyOS 中CustomDialog装饰器用于创建自定义对话框。与系统提供的标准对话框不同自定义对话框可以完全控制布局和交互逻辑。CustomDialogstruct TimePickerDialogContent{controller:CustomDialogController// 对话框控制器// ... 其他属性和方法}2. CustomDialogController 对话框控制器CustomDialogController用于控制对话框的显示和关闭。在父组件中创建控制器实例然后调用open()方法显示对话框。privatetimePickerController:CustomDialogController|nullnull// 创建并打开对话框this.timePickerControllernewCustomDialogController({builder:TimePickerDialogContent({/* 参数 */}),autoCancel:true,alignment:DialogAlignment.Center})this.timePickerController.open()builder自定义弹窗内容构造器。autoCancel是否允许点击遮障层退出true表示关闭弹窗。false表示不关闭弹窗。alignment弹窗在竖直方向上的对齐方式。3. State 状态管理State装饰器用于声明组件的状态变量。当状态变量的值发生变化时UI 会自动更新。StatetempHour:number0// 临时存储选中的小时StatetempMinute:number0// 临时存储选中的分钟完整实现第一步定义对话框结构首先我们创建一个自定义对话框组件定义它需要的属性CustomDialogstruct TimePickerDialogContent{controller:CustomDialogController// 对话框控制器必需selectedTime:DatenewDate()// 当前选中的时间onConfirm:(hour:number,minute:number)void(){}// 确认回调StatetempHour:number0// 临时小时值StatetempMinute:number0// 临时分钟值// 小时选项0-23privatehours:string[][00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23]// 分钟选项只有 00 和 30privateminutes:string[][00,30]// ... 后续代码}这边我们写的已经很清楚了根据我们的需求小时的选项是完整的从0-23但是分钟的选项只有00和30这是根据我们的需求来设定的。第二步初始化时间值在对话框显示之前我们需要将传入的selectedTime转换为小时和分钟并调整到最近的半小时aboutToAppear():void{// 获取小时0-23this.tempHourthis.selectedTime.getHours()// 将分钟调整为最近的半小时constminutesthis.selectedTime.getMinutes()if(minutes15){// 0-14分钟 → 向下取整到 00this.tempMinute0}elseif(minutes45){// 15-44分钟 → 向上取整到 30this.tempMinute30}else{// 45-59分钟 → 向上取整到下一个小时的 00this.tempHour(this.tempHour1)%24// % 24 确保不超过 23this.tempMinute0}}代码说明aboutToAppear()是组件生命周期方法在组件即将显示时调用我们将任意分钟值调整为 00 或 30这样用户看到的初始值就是半小时对齐的使用% 24确保小时值在 0-23 范围内例如 23 点 50 分会变成 0 点 00 分第三步构建 UI 布局接下来我们使用build()方法构建对话框的 UIbuild(){Column(){// 标题Text(选择时间).fontSize(18).fontWeight(FontWeight.Bold).fontColor($r(app.color.text_primary)).margin({bottom:12})// 提示文字Text(仅支持半小时为单位).fontSize(12).fontColor($r(app.color.text_secondary)).margin({bottom:16})// 时间选择器区域Row(){// 小时选择器Column(){Text(小时).fontSize(12).fontColor($r(app.color.text_secondary)).margin({bottom:8})TextPicker({range:this.hours,// 选项数组selected:this.tempHour// 默认选中项的索引}).onChange((value:string|string[],index:number|number[]){// 当用户滑动选择器时触发if(typeofindexnumber){this.tempHourindex// 更新小时值}})}.layoutWeight(1)// 占据一半宽度// 分隔符Text(:).fontSize(24).fontWeight(FontWeight.Bold).fontColor($r(app.color.text_primary)).margin({left:12,right:12})// 分钟选择器Column(){Text(分钟).fontSize(12).fontColor($r(app.color.text_secondary)).margin({bottom:8})TextPicker({range:this.minutes,selected:this.tempMinute0?0:1// 0分钟→索引030分钟→索引1}).onChange((value:string|string[],index:number|number[]){if(typeofindexnumber){// 将索引转换为实际分钟值this.tempMinuteindex0?0:30}})}.layoutWeight(1)}.width(100%).margin({bottom:16})// 显示当前选中的时间Text(已选择:${this.tempHour.toString().padStart(2,0)}:${this.tempMinute.toString().padStart(2,0)}).fontSize(16).fontWeight(FontWeight.Bold).fontColor($r(app.color.primary_color)).margin({bottom:16})// 按钮区域Row(){// 取消按钮Button(取消).fontSize(15).fontColor($r(app.color.text_secondary)).backgroundColor($r(app.color.input_background)).borderRadius(22).layoutWeight(1).height(44).onClick((){this.controller.close()// 关闭对话框不返回任何值})// 确定按钮Button(确定).fontSize(15).fontColor(Color.White).backgroundColor($r(app.color.primary_color)).borderRadius(22).layoutWeight(1).height(44).margin({left:10}).onClick((){// 调用回调函数将选中的时间传回父组件this.onConfirm(this.tempHour,this.tempMinute)this.controller.close()// 关闭对话框})}.width(100%)}.width(75%)// 对话框宽度为屏幕的 75%.padding(20).backgroundColor($r(app.color.card_background))// 使用主题颜色.borderRadius(16)// 圆角}第四步在父组件中使用现在我们在父组件中创建并打开这个时间选择器Componentexportstruct AddTimeBlockDialog{StatestartTime:DatenewDate()// 开始时间StateendTime:DatenewDate()// 结束时间privatestartTimePickerController:CustomDialogController|nullnull// 格式化时间显示例如14:30privateformatTime(date:Date):string{consthoursdate.getHours().toString().padStart(2,0)constminutesdate.getMinutes().toString().padStart(2,0)return${hours}:${minutes}}// 打开开始时间选择器privateopenStartTimePicker():void{this.startTimePickerControllernewCustomDialogController({builder:TimePickerDialogContent({selectedTime:this.startTime,// 传入当前时间onConfirm:(hour:number,minute:number){// 用户点击确定后更新开始时间constnewTimenewDate(this.startTime)newTime.setHours(hour)newTime.setMinutes(minute)newTime.setSeconds(0)newTime.setMilliseconds(0)this.startTimenewTime// 更新状态UI 会自动刷新}}),autoCancel:true,// 点击对话框外部自动关闭alignment:DialogAlignment.Center,// 居中显示customStyle:true// 使用自定义样式})this.startTimePickerController.open()// 显示对话框}build(){Column(){// 开始时间按钮Button(){Column(){Text(开始).fontSize(11).fontColor($r(app.color.text_secondary))Text(this.formatTime(this.startTime)).fontSize(16).fontWeight(FontWeight.Medium).fontColor($r(app.color.text_primary)).margin({top:2})}}.backgroundColor($r(app.color.input_background)).borderRadius(10).padding(12).onClick((){this.openStartTimePicker()// 点击按钮打开选择器})}}}这边来具体讲一下相关的配置CustomDialogController 配置builder指定对话框的内容组件autoCancel是否允许点击外部关闭alignment对话框在屏幕上的位置customStyle是否使用自定义样式如果为 false会使用系统默认样式回调函数onConfirm是一个箭头函数当用户点击确定时被调用我们在回调中更新startTime状态UI 会自动刷新显示新时间Date 对象操作创建新的 Date 对象new Date(this.startTime)设置小时和分钟setHours()和setMinutes()清零秒和毫秒确保时间精确到分钟总结通过本教程我们学习了如何在 HarmonyOS 中实现一个自定义时间选择器。也通过一个案例知道了如何在实践中实现。这个时间选择器可以直接应用到你的项目中也可以根据需求进行扩展和定制。希望这篇教程对你有所帮助参考资料HarmonyOS 官方文档 - CustomDialogHarmonyOS 官方文档 - TextPicker

相关新闻

维萨拉 HMD60Y-G1550010 管道露点温湿度变送器全解析|选型、接线、PLC 对接、故障排查

维萨拉 HMD60Y-G1550010 管道露点温湿度变送器全解析|选型、接线、PLC 对接、故障排查

一、前言在洁净厂房、数据中心、实验室、工业烘干、HVAC 风道控湿场景中,露点、温湿度实时稳定采集是工艺达标核心前提。VAISALA 维萨拉 HMD60Y-G1550010 作为经典管道插入式变送器,搭载原厂 HUMICAP 湿敏传感芯片,支持露点、湿球、焓值多参数…

2026/7/22 23:16:08阅读更多 →
Windows系统文件DWrite.dll丢失找不到问题解决

Windows系统文件DWrite.dll丢失找不到问题解决

在使用电脑系统时经常会出现丢失找不到某些文件的情况,由于很多常用软件都是采用 Microsoft Visual Studio 编写的,所以这类软件的运行需要依赖微软Visual C运行库,比如像 QQ、迅雷、Adobe 软件等等,如果没有安装VC运行库或者安装…

2026/7/22 23:16:08阅读更多 →
【单片机毕业设计】基于 STM32 的智能噪声监测与远程预警系统设计,基于 STM32 单片机的环境噪声采集与物联网监测装置设计(010903)

【单片机毕业设计】基于 STM32 的智能噪声监测与远程预警系统设计,基于 STM32 单片机的环境噪声采集与物联网监测装置设计(010903)

文章目录20 个相关毕业设计备选题目项目研究背景摘要总体方案核心功能基础功能核心功能拓展辅助功能技术路线项目演示关于我们项目案例源码获取博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作…

2026/7/22 23:16:08阅读更多 →
电商多平台运作工具有哪些?六大类工具全链路盘点

电商多平台运作工具有哪些?六大类工具全链路盘点

打开任何一个跨境电商社群,都能看到卖家在问:"亚马逊加TikTok Shop加Temu,到底需要哪些工具?"问的人很多,但真正能系统回答的很少。如果你需要一个能替代Excel、自动同步多平台数据、零代码搭建跨平台看板的…

2026/7/23 0:22:35阅读更多 →
《解压Zip文件》二、启动一个Worker指南

《解压Zip文件》二、启动一个Worker指南

HarmonyOS ohos.worker (启动一个Worker) 使用指南:多线程实战详解模块类型:系统内置模块 关键词:Worker、多线程、后台任务、线程通信、ArkTS效果一、为什么需要 Worker? 在 HarmonyOS 应用中,主线程(UI 线…

2026/7/23 0:22:35阅读更多 →
200行代码硬核读取ext4磁盘文件

200行代码硬核读取ext4磁盘文件

我们可能听说过很多文件系统,比如 FAT32、NTFS、EXT4,在linux 下 EXT4 是一个使用比较广泛的文件系统,前面的小节我们简单介绍了 EXT4 文件系统的内部结构,这个小节我们用硬核方式读取 EXT4 文件系统下 /etc/hosts 文件&#xff0…

2026/7/23 0:20:34阅读更多 →
2026年最新英语写作批改平台挑选指南 附实用避坑技巧

2026年最新英语写作批改平台挑选指南 附实用避坑技巧

文章摘要:随着英语写作批改需求快速增长,市场上涌现了大量智能批改工具,但质量参差不齐,普通用户往往难以甄别。本文旨在帮助读者厘清核心评估维度,从技术能力、场景适配、合规安全等角度系统梳理挑选标准,…

2026/7/23 0:20:34阅读更多 →
2026 Cloudflare 5秒盾解决指南:无限验证码、403拦截与Bot检测优化方法

2026 Cloudflare 5秒盾解决指南:无限验证码、403拦截与Bot检测优化方法

在2026年的企业数字化运营中,公开数据采集、自动化测试、SEO监控已成为核心基础设施。然而,随着 Cloudflare 将其防护机制全面升级为以 Turnstile(无感验证) 和 AI 驱动的行为生物识别(Behavioral Biometrics&#xff…

2026/7/23 0:20:34阅读更多 →
损失函数与训练细节——这些坑我替你踩过了

损失函数与训练细节——这些坑我替你踩过了

先聊聊 Loss 函数。语义分割最基础的 Loss 是 Cross-Entropy(交叉熵),简单粗暴,逐像素计算分类损失。但你很快会发现一个问题——类别不平衡。Cityscapes 里“道路”和“建筑”占了画面大半江山,而“摩托车”、“自行车…

2026/7/23 0:18:34阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 0:53:59阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 0:53:59阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 0:53:59阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:00:28阅读更多 →
从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:28阅读更多 →
油泥处理设备哪里能买到

油泥处理设备哪里能买到

油泥处理设备哪里有?这是许多从事油田、炼化、清罐业务的从业者最关心的问题。根据河南三丰环保设备有限公司的行业经验,选购油泥处理设备的核心在于设备能否适配当地环保法规与原料特性,而非单纯看价格。该公司总经理王钦田先生指出&#xf…

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

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

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

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

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

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

2026/7/22 18:55:50阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

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

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

2026/7/22 18:55:50阅读更多 →