【HarmonyOS 6】HarmonyOS 自定义时间选择器实现

发布时间:2026/9/12 22:27:52

【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
延伸阅读

更多相关文章

2026/9/12 22:26:54

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

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

2026/9/11 4:58:22

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

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

2026/9/12 22:26:09

Pygame 2048完整工程:含BDF字体、虚拟环境脚本与状态机实现

简介:本资源是一套基于Python与Pygame实现的2048小游戏完整可运行项目,面向Python初学者及游戏开发入门者,旨在通过经典数字拼图游戏实践掌握图形界面编程、事件驱动逻辑与二维数组算法设计。压缩包共865个文件,含466个核心.py源码…

2026/9/12 22:26:09

YOLOv9 PCB缺陷检测实战:1297张图数据集训练与优化全解析

简介:该数据集面向PCB电路板质检与计算机视觉缺陷检测场景,采用YOLOv9格式标注,包含1297张真实PCB板图片,整体识别准确率可达99.8%。压缩包内共2000个文件,其中702张JPG原图、1297个TXT标注文件以及1个YAML配置文件&am…

2026/9/12 22:26:09

2722张图像训练YOLO杂草检测模型全流程

简介:这份杂草与作物目标检测数据集专门面向yolo系列算法开发者与农业智能化研究人员,包含2722张已标注图像,覆盖杂草和作物两类目标,可直接用于模型训练、验证与测试。数据集已预先划分好训练集、验证集,并附带data.y…

2026/9/12 22:26:09

YOLO训练从数据开始:杂草与作物数据集的全流程实操

简介:面向yolo系列算法目标检测任务的杂草与作物数据集,涵盖杂草和作物两大类目标,适用于农业场景下的模型训练、算法验证与精准作业,可配合yolov5、yolov7、yolov8、yolov9、yolov10、yolo11等主流框架使用,为精确除草…

2026/9/12 22:26:09

Python实战:从零搭建人脸识别门禁系统

简介:以人脸识别为核心的门禁管理系统,整合了宿舍管理、水电费充值、报修、系统日志等模块,面向高校宿舍场景,适合毕业设计或学习Django与Dlib人脸识别的开发者。压缩包共2001个文件,以1668个Python源码文件为主&#…

2026/9/12 2:05:33

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/12 3:55:12

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/12 10:09:03

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/12 0:04:17

MATLAB仿生优化框架:长鼻浣熊算法多策略融合实现

简介:本资源是一份面向智能优化算法研究者与MATLAB初学者的仿生智能算法实践代码包,聚焦于长鼻浣熊优化算法(COA)的多策略改进与性能验证。针对传统COA易陷局部最优、收敛精度不足等问题,作者融合Circle映射初始化提升…

2026/9/12 0:04:17

【JAVA毕设源码分享】基于 JavaWeb 的校园一卡通管理系统的设计与实现 基于 JavaWeb 的校园卡业务管理系统(程序+文档+代码讲解+一条龙定制)

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

2026/9/12 0:04:17

【JAVA毕设源码分享】基于 Java 的图书馆借阅管理平台的搭建与实现 基于 Java 的图书馆综合管理系统(程序+文档+代码讲解+一条龙定制)

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

2026/9/12 6:29:36

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/12 14:32:17

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/12 6:37:43

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码