鸿蒙4.0开发实战(ArkTS)-闹钟制作

闹钟功能要求

  1. 展示指针表盘或数字时间。
  2. 添加、修改和删除闹钟。
  3. 展示闹钟列表,并可打开和关闭单个闹钟。
  4. 闹钟到设定的时间后弹出提醒。
  5. 将闹钟的定时数据保存到轻量级数据库。

闹钟主界面

闹钟界面包括当前时间、闹钟列表、添加闹钟子组件,具体包括以下模块:

  • 展示当前时间。
  • 展示闹钟列表。
  • 添加闹钟。
  • 后台代理提醒。

展示当前时间

当前时间使用了Canvas组件绘制,默认展示指针表盘,点击表盘区域切换为数字时钟。效果如图所示:

在主页的ClockArea组件中初始化Canvas画布,并绑定指针表盘和数字时钟切换事件。

// ClockArea.ets
@Component
export default struct ClockArea {build() {Canvas(this.renderContext).width(this.canvasSize).aspectRatio(CommonConstants.DEFAULT_LAYOUT_WEIGHT).onReady(() => {if (this.drawInterval === CommonConstants.DEFAULT_NUMBER_NEGATIVE) {// 启动绘画任务    this.startDrawTask();}}).onClick(() => {this.showClock = !this.showClock;})}...// 启动绘画任务private startDrawTask() {let that = this;that.renderContext.translate(this.canvasSize / CommonConstants.DEFAULT_DOUBLE,this.canvasSize / CommonConstants.DEFAULT_DOUBLE);that.drawClockArea();this.drawInterval = setInterval(() => {that.drawClockArea();}, MainConstant.DEFAULT_ONE_SECOND_MS);}
}

绘画任务是使用CanvasRenderingContext2D对象在Canvas画布组件上绘制指针表盘和数字时钟。

// ClockArea.ets
// 开始绘制时钟区域
private drawClockArea(): void {this.renderContext.clearRect(-this.canvasSize,-this.canvasSize / CommonConstants.DEFAULT_DOUBLE,this.canvasSize * CommonConstants.DEFAULT_DOUBLE,this.canvasSize);let date = new Date();let hours = date.getHours();let minutes = date.getMinutes();let seconds = date.getSeconds();if (this.showClock) {// 绘制表盘时钟...} else {// 绘制数字时钟...}
}

展示闹钟列表

展示已添加的闹钟信息,可对闹钟进行启停操作,点击闹钟可跳转到闹钟操作界面(修改和删除闹钟)。主页启动后获取轻量级数据库中的闹钟定时数据,并监控数据库数据变化。

// MainViewModel.ets
public queryAlarmsTasker(callback: (alarms: Array<AlarmItem>) => void) {let that = this;that.queryDatabaseAlarms(callback);let preference = GlobalContext.getContext().getObject('preference') as PreferencesHandler;preference.addPreferencesListener({onDataChanged() {that.queryDatabaseAlarms(callback);}} as PreferencesListener)
}

在AlarmList.ets中添加闹钟列表子组件,并绑定启停、跳转事件。

// AlarmList.ets
@Component
export default struct AlarmList {@Link alarmItems: Array<AlarmItem>;build() {List({ space: DimensionUtil.getVp($r('app.float.alarm_list_space')) }) {ForEach(this.alarmItems, (item: AlarmItem) => {ListItem() {AlarmListItem({ alarmItem: item })}.onClick(() => {router.pushUrl({ url: 'pages/DetailIndex', params: { alarmItem: item } });})}, (item: AlarmItem) => JSON.stringify(item))}.padding({left: DimensionUtil.getVp($r('app.float.alarm_list_content_distance')),right: DimensionUtil.getVp($r('app.float.alarm_list_content_distance'))}).listDirection(Axis.Vertical).layoutWeight(CommonConstants.DEFAULT_LAYOUT_WEIGHT).margin({ top: DimensionUtil.getVp($r('app.float.alarm_list_content_distance')) })}
}

添加闹钟

点击界面底部闹钟添加按钮,跳转到闹钟操作界面(新增闹钟)。效果如图所示:

在MainIndex.ets中为添加按钮绑定跳转事件。

// MainIndex.ets
@Entry
@Component
struct MainIndex {...build() {Column() {...Button() {Image($r('app.media.ic_add')).objectFit(ImageFit.Fill)}....onClick(() => {router.pushUrl({ url: 'pages/DetailIndex' });})}...}
}

后台代理提醒

根据闹钟列表中的数据来设置(启停)闹钟实例。

// MainViewModel.ets
// 开启/关闭闹钟
public openAlarm(id: number, isOpen: boolean) {for (let i = 0; i < this.alarms.length; i++) {if (this.alarms[i].id === id) {this.alarms[i].isOpen = isOpen;if (isOpen) {this.reminderService.addReminder(this.alarms[i]);} else {this.reminderService.deleteReminder(this.alarms[i].id);}let preference = GlobalContext.getContext().getObject('preference') as PreferencesHandler;preference.set(CommonConstants.ALARM_KEY, JSON.stringify(this.alarms));break;}}
}

闹钟详情界面

闹钟操作界面分为新增和修改界面,其中在修改界面可删除闹钟。具体包括以下模块:

  • 退出或保存详情。
  • 设置闹钟时间。
  • 设置闹钟详情。
  • 提供后台代理提醒能力

退出或保存详情

点击左上角“x”图标关闭操作界面,关闭闹钟操作界面子组件,点击右上角“√”图标,保存当前设置并关闭操作界面。

在DetailIndex.ets入口页面中引入头部组件BackContainer,自定义了返回按钮和返回逻辑操作,添加确定(“√”)子组件,并绑定点击事件。

// BackContainer.ets
build() {Row() {Button() {Image(this.backImgRes == null ? $r('app.media.ic_public_back') : this.backImgRes).objectFit(ImageFit.Fill)}.backgroundColor($r('app.color.trans_parent')).width(DimensionUtil.getVp($r('app.float.title_button_size'))).height(DimensionUtil.getVp($r('app.float.title_button_size'))).onClick(() => {this.backFunc ? this.backFunc() : router.back();})Text(this.header).fontSize(DimensionUtil.getFp($r('app.float.detail_title_font_size'))).lineHeight(DimensionUtil.getVp($r('app.float.title_line_height'))).margin({ left: DimensionUtil.getVp($r('app.float.title_margin')) }).fontColor($r('app.color.grey_divider')).fontWeight(FontWeight.Bold)Blank()if (this.closer) {this.closer();}}.padding({left: DimensionUtil.getVp($r('app.float.title_horizon_margin')),right: DimensionUtil.getVp($r('app.float.title_horizon_margin'))}).height(DimensionUtil.getVp($r('app.float.page_title_height'))).width(CommonConstants.FULL_LENGTH)
}

设置闹钟时间

设置闹钟提醒时间,在闹钟操作界面可通过滑动选择器设置闹钟的提醒时间(包括:时段、小时、分钟)。详情页DetailIndex.ets中添加闹钟时间选择器子组件DatePickArea.ets。

// DatePickArea.ets
@Component
export default struct DatePickArea {build() {Stack({ alignContent: Alignment.Center }) {Row() {ForEach(DetailConstant.DAY_DATA, (item: DayDataItem) => {TextPicker({ range: item.data, selected: item.delSelect }).layoutWeight(CommonConstants.DEFAULT_LAYOUT_WEIGHT).backgroundColor($r('app.color.grey_light')).onChange((value: string, index: number) => {item.delSelect = index;})}, (item: DayDataItem) => JSON.stringify(item))}}.height(DimensionUtil.getVp($r('app.float.date_picker_height'))).padding({left: DimensionUtil.getVp($r('app.float.date_picker_padding_horizon')),right: DimensionUtil.getVp($r('app.float.date_picker_padding_horizon'))})}
}

设置闹钟时间

设置闹钟提醒时间,在闹钟操作界面可通过滑动选择器设置闹钟的提醒时间(包括:时段、小时、分钟)。详情页DetailIndex.ets中添加闹钟时间选择器子组件DatePickArea.ets。

// DatePickArea.ets
@Component
export default struct DatePickArea {build() {Stack({ alignContent: Alignment.Center }) {Row() {ForEach(DetailConstant.DAY_DATA, (item: DayDataItem) => {TextPicker({ range: item.data, selected: item.delSelect }).layoutWeight(CommonConstants.DEFAULT_LAYOUT_WEIGHT).backgroundColor($r('app.color.grey_light')).onChange((value: string, index: number) => {item.delSelect = index;})}, (item: DayDataItem) => JSON.stringify(item))}}.height(DimensionUtil.getVp($r('app.float.date_picker_height'))).padding({left: DimensionUtil.getVp($r('app.float.date_picker_padding_horizon')),right: DimensionUtil.getVp($r('app.float.date_picker_padding_horizon'))})}
}

设置闹钟详情

// SettingItem.ets
build() {Column() {ForEach(this.settingInfo, (item: AlarmSettingItem, index: number | undefined) => {Divider()...Row() {Text(item.title)...Text(item.content)...Image($r('app.media.ic_right'))...}....onClick(() => {this.showSettingDialog(item.sType);})}, (item: AlarmSettingItem, index: number | undefined) => JSON.stringify(item) + index)}...
}

提供后台代理提醒能力

导入系统提醒服务类ReminderService.ets,它由系统后台代理提醒能力封装,支持新增、修改、删除系统闹钟功能,在设置、删除闹钟后同步更新到轻量级数据库中并刷新主页页面。

// DetailViewModel.ets
public async setAlarmRemind(alarmItem: AlarmItem) {alarmItem.hour = this.getAlarmTime(CommonConstants.DEFAULT_SINGLE);alarmItem.minute = this.getAlarmTime(CommonConstants.DEFAULT_DATA_PICKER_HOUR_SELECTION);let index = await this.findAlarmWithId(alarmItem.id);if (index !== CommonConstants.DEFAULT_NUMBER_NEGATIVE) { // 已存在,删除原有提醒this.reminderService.deleteReminder(alarmItem.id);} else { // 不存在,以数据长度为notificationId新增闹钟数据index = this.alarms.length;alarmItem.notificationId = index;this.alarms.push(alarmItem);}this.reminderService.addReminder(alarmItem, (newId: number) => {alarmItem.id = newId;alarmItem.isOpen = true;this.alarms[index] = alarmItem;let preference = GlobalContext.getContext().getObject('preference') as PreferencesHandler;preference.set(CommonConstants.ALARM_KEY, JSON.stringify(this.alarms));})
}public async removeAlarmRemind(id: number) {this.reminderService.deleteReminder(id);let index = await this.findAlarmWithId(id);if (index !== CommonConstants.DEFAULT_NUMBER_NEGATIVE) {this.alarms.splice(index, CommonConstants.DEFAULT_SINGLE);}let preference = GlobalContext.getContext().getObject('preference') as PreferencesHandler;preference.set(CommonConstants.ALARM_KEY, JSON.stringify(this.alarms));
}

全文是对鸿蒙开发的技术运用,更多的鸿蒙开发实战技术,可以前往主页查看更多信息。分享一份鸿蒙的学习路线图(略缩版),高清完整版在主页找我保存。

最后

实现一个简易闹钟效果图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/595956.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

共享企业文件数据信息:实用方法与技巧分享

在当下快节奏的企业办公生活中&#xff0c;如何有效且高效的进行企业文件数据信息共享&#xff0c;保持企业竞争力&#xff0c;是许多企业团队面临的问题。 诚然&#xff0c;社交媒体工具的出现可以缓解企业信息共享协作的痛点。然而&#xff0c;多平台工具的交叉使用又使企业…

Zuul相关面试题及到案(2024)

1、什么是Zuul&#xff1f;它在微服务架构中有什么作用&#xff1f; Zuul是Netflix开源的一种提供API网关服务的应用程序&#xff0c;它在微服务架构中扮演着流量的前门角色。主要功能包括以下几点&#xff1a; 路由转发&#xff1a;Zuul网关将外部请求转发到具体的微服务实例…

斯坦福和 Meta学者发现Gemini在常识推理任务中有较强潜力;初学者GPT:Ai和LLM资源

&#x1f989; AI新闻 &#x1f680; 斯坦福和 Meta学者发现Gemini在常识推理任务中有较强潜力 摘要&#xff1a;斯坦福和Meta的学者发表论文为Gemini正名&#xff0c;他们发现之前对Gemini的评估并不能完全捕捉到其真正的常识推理潜力。他们设计了需要跨模态整合常识知识的任…

vue-mixins混入处理

定义 mixins&#xff08;混入&#xff09;&#xff1a;一种分发 Vue 组件中可复用功能的非常灵活的方式&#xff0c;mixins 是一个 js 对象&#xff0c;它可以包含我们组件script中的任意功能选项&#xff0c;如&#xff1a;data、components、methods、created、computed 等等…

MySQL 存储引擎和索引类型介绍

1. 引言 MySQL 是一个流行的关系型数据库管理系统&#xff0c;提供多种存储引擎以满足不同的业务需求。本文将介绍几种常见的 MySQL 存储引擎和索引类型比较&#xff0c;并给出相应的示例。 2. 存储引擎概述 2.1 InnoDB 存储引擎 InnoDB 是 MySQL 的默认存储引擎&#xff0…

多线程实践项目

前言 前面几篇文章分别学习了多线程的基本知识和线程池使用&#xff0c;这篇则为项目实践和整理。 项目参考 选择了两个项目github地址&#xff0c;如果不方便下载可以下面留言评论私发。 1.马士兵老师的juc&#xff0c;讲述了多线程的基本知识线程讲解 2.基本的线程演示&am…

学习JavaEE的日子 day08 方法的重载,递归,万年历

day08 1.方法的重载 >理解&#xff1a;方法与方法之间的关系> 条件&#xff1a;> 1.方法必须在同一个类中> 2.方法名必须一致> 3.参数列表的个数或者类型不一致> 4.与返回值无关> 好处&#xff1a;系统会根据具体实参类型自动匹配到对应的方法…

【vue】emit 的理解与使用

文章目录 介绍流程示例效果父组件子组件 介绍 $emit 是 Vue 组件实例中的一个方法&#xff0c;用来触发自定义事件&#xff0c;并向父组件传递信息它接受两个参数&#xff1a;事件名称和可选参数this.$emit(事件名称, 参数);流程 示例 效果 触发前 触发后 父组件 父组件使…

FBL刷写

刷写 1、刷写需求的理解2、刷写流程2.1、预编程阶段&#xff1a;保证在编程阶段的动作能够正常操作&#xff0c;控制器给响应。整车功能不会出现问题 刷写某一控制器时&#xff0c;避免其他控制器集DTC,85控制DTC&#xff1b; 28 通信控制.保证总线负载率不要过高&#xff08;下…

shell脚本实现九九乘法表

9*9乘法表 判断服务是否开启 1.查看80端口是否被监听 [rootlocalhost ~]# ss -an | grep 80 tcp LISTEN 0 128 *:80 *:* 2.查看80端口/httpd服务是否开启 [rootlocalhost ~]# n…

AndroidStudio导入jar包

目录 1. 转为Project模式 2. 将jar文件粘贴到app/libs文件夹中 3. 右键jar 包&#xff0c;点击Add As Library 在AndroidStudio中导入jar包&#xff08;jar文件&#xff09;。 1. 转为Project模式 2. 将jar文件粘贴到app/libs文件夹中 3. 右键jar 包&#xff0c;点击Add As…

109-Gradle构建工具的学习

Gradle构建工具的学习 Gradle 简介&#xff1a; Gradle 是一款Google 推出的基于 JVM、通用灵活的项目构建工具&#xff0c;支持 Maven&#xff0c;JCenter 多种第三方仓库&#xff0c;支持传递性依赖管理、废弃了繁杂的xml 文件&#xff0c;转而使用简洁的、支持多种语言&am…

jmeter使用心得(一)

jmeter作为接口测试的常用工具之一&#xff0c;在我们的测试中经常会用到&#xff0c;往期的文章中&#xff0c;我们也分享过jmeter的各种功能和用法&#xff0c;基本覆盖了方方面面&#xff0c;可以满足各种接口测试的需求。但实际测试中我们也会发现&#xff0c;jmeter这么强…

前置微小信号放大器有哪些经典应用场景

前置微小信号放大器是电子系统中的关键组件&#xff0c;用于放大输入信号的微小幅度&#xff0c;以提高信号与噪声比和系统的灵敏度。这些放大器在各种应用中发挥着关键作用&#xff0c;以下是前置微小信号放大器的一些经典应用场景&#xff1a; 通信系统&#xff1a; 前置微小…

CSS案例:flex、justify-content、align-items

黑马程序员JS学习时的一个案例&#xff0c;CSS有点不懂&#xff0c;单拎出来分析。 具体出处是某站视频中的数组篇讲解&#xff0c;&#xff08;点击链接跳转&#xff09; CSS案例 效果&代码1. 先分析最大的boxflex布局 justify-contentalign-items以 flex-end 为例 2. box…

公众号文章如何提高阅读量?媒介盒子教你几招

公众号作为微信运营的主要载体&#xff0c;做得好就能让品牌得到大量曝光&#xff0c;公众号文章作为长文案想要写好还需要一定的技术&#xff0c;今天媒介盒子就来和大家聊聊公众号文章怎么写才能提高阅读量&#xff1a; 一、 内容干货满足读者求知欲 只要你的文章实用性强&…

(17)Linux的进程阻塞进程程序替换 exec 函数簇

前言&#xff1a;本章我们讲解它的 options 参数。在讲解之前我们需要理解进程阻塞&#xff0c;然后我们重点讲解二进程程序替换&#xff0c;这是本章的重点&#xff0c;然后介绍一个进程替换函数 execl&#xff0c;通过介绍这个函数来打开突破口&#xff0c;引入进程创建的知识…

openmediavault(OMV) (27)网络(2)adguardhome

简介 AdGuard Home 是一个开源的网络广告和隐私保护解决方案,它充当局域网中的 DNS 服务器,提供广告拦截、跟踪器阻止和家长控制等功能。它可以在个人电脑、树莓派或其他支持的硬件设备上运行。 AdGuard Home 的主要功能包括: 广告拦截:AdGuard Home 使用广泛维护的广告…

数据湖的概念

1.定义 不同的公司对数据湖有不同的描述&#xff1a; 维基百科&#xff1a;数据湖是一类存储数据自然/原始格式的系统或存储&#xff0c;通常是对象块或者文件。数据湖通常是企业中全量数据的单一存储。全量数据包括原始系统所产生的原始数据拷贝以及为了各类任务而产生的转换…

基于人工智能的数据库工具Chat2DB使用

文章目录 前言Chat2DB介绍Chat2DB地址下载安装 Chat2DB配置Chat2DB使用1、自然语言转sql2. SQL解释3. SQL优化4. SQL转换 写在最后 前言 随着人工智能的发展&#xff0c;各行各业都出现了不少基于AI的工具来提升工作效率。就连国内的各个大厂也都在基于大模型开发自己的产品线…