首页 | 详情页 |
---|---|
1import { CanvasComp } from '../components/CanvasComp'
2import { ClockItemComp } from '../components/ClockItemComp'
3
4@Entry
5@Component
6struct Index {
7 build() {
8 Stack({ alignContent: Alignment.Bottom }){
9 Column({ space: 15 }) {
10 Text('闹钟')
11 .fontSize('24')
12 .width('100%')
13
14 CanvasComp()
15
16 ForEach([1, 2, 3], () => {
17 ClockItemComp()
18 .onClick(() => {
19 router.pushUrl({
20 url: 'pages/DetailPage',
21 })
22 })
23 })
24 }
25 .padding(15)
26 .height('100%')
27 .width('100%')
28 .backgroundColor('#f5f5f5')
29 // 添加
30 Text('+')
31 .width(50)
32 .aspectRatio(1)
33 .backgroundColor('#06f')
34 .fontSize(40)
35 .fontWeight(100)
36 .fontColor('#fff')
37 .borderRadius(25)
38 .textAlign(TextAlign.Center)
39 .margin({ bottom: 50 })
40 .onClick(() => {
41 router.pushUrl({
42 url: 'pages/DetailPage',
43 })
44 })
45 }
46 }
47}
1@Component
2export struct CanvasComp {
3 build() {
4
5 }
6}
1@Component
2export struct ClockItemComp {
3 build() {
4
5 }
6}
1@Component
2export struct CanvasComp {
3 private settings = new RenderingContextSettings(true)
4 private context = new CanvasRenderingContext2D(this.settings)
5 private panImg = new ImageBitmap('/images/ic_clock_pan.png')
6 private hourImg = new ImageBitmap('/images/ic_hour_pointer.png')
7 private minuteImg = new ImageBitmap('/images/ic_minute_pointer.png')
8 private secondImg = new ImageBitmap('/images/ic_second_pointer.png')
9
10 // 画布尺寸
11 canvasSize = 252
12 // 指针尺寸
13 pointerWidth = 8
14
15 startDraw() {
16 this.drawClock()
17 setInterval(() => {
18 this.drawClock()
19 }, 1000)
20 }
21
22 /**
23 * 绘制闹钟
24 */
25 drawClock() {
26 this.context.clearRect(0, 0, this.canvasSize, this.canvasSize)
27 this.context.drawImage(this.panImg, 0, 0, this.canvasSize, this.canvasSize)
28 // 根据时间绘制指针
29 const date = new Date()
30 const hour = date.getHours()
31 const minute = date.getMinutes()
32 const second = date.getSeconds()
33 this.drawPointer(this.hourImg, hour % 12 / 12 * 360)
34 this.drawPointer(this.minuteImg, minute / 60 * 360)
35 this.drawPointer(this.secondImg, second / 60 * 360)
36 }
37
38 /**
39 * 绘制指针
40 * @param img - 指针图片
41 * @param angle - 旋转角度,起点是 Y 轴上方向
42 */
43 drawPointer(img: ImageBitmap, angle: number) {
44 this.context.save()
45 this.context.translate(this.canvasSize / 2, this.canvasSize / 2)
46 this.context.rotate((angle + 180) * Math.PI / 180)
47 this.context.translate(-this.canvasSize / 2, -this.canvasSize / 2)
48 this.context.drawImage(img, this.canvasSize / 2 - this.pointerWidth / 2, 0, this.pointerWidth, this.canvasSize)
49 this.context.restore()
50 }
51
52 build() {
53 Canvas(this.context)
54 .width(this.canvasSize)
55 .aspectRatio(1)
56 .onReady(() => {
57 this.startDraw()
58 })
59 }
60}
1@Component
2export struct ClockItemComp {
3 build() {
4 Row(){
5 Column({ space: 5 }) {
6 Row({ space: 5 }){
7 Text('下午')
8 .fontColor('#666')
9 Text('04:30')
10 .fontWeight(600)
11 .fontSize(18)
12 }
13 Row({ space: 15 }){
14 Text('闹钟')
15 .fontColor('#999')
16 .fontSize(14)
17 Text('不重复')
18 .fontColor('#999')
19 .fontSize(14)
20 }
21 }
22 .alignItems(HorizontalAlign.Start)
23
24 // 开关
25 Toggle({ type: ToggleType.Switch , isOn: true })
26 }
27 .height(64)
28 .padding({ left: 20, right: 15 })
29 .width('100%')
30 .backgroundColor('#fff')
31 .borderRadius(30)
32 .justifyContent(FlexAlign.SpaceBetween)
33 }
34}
1@Entry
2@Component
3struct DetailPage {
4
5 submit () {
6 // TODO
7 }
8
9 @Builder
10 CellBuilder (title: string, value: string) {
11 Row(){
12 Text(title)
13 .layoutWeight(1)
14 Text(value)
15 .fontColor('#999')
16 Image('/images/ic_public_arrow_right.svg')
17 .width(18)
18 .aspectRatio(1)
19 .fillColor('#999')
20 }
21 .height(60)
22 .padding({ left: 15, right: 15 })
23 .backgroundColor('#fff')
24 }
25
26 build() {
27 Navigation(){
28 Column({ space: 15 }){
29 TimePicker()
30 .borderRadius(16)
31 .clip(true)
32
33 Column({ space: 1 }){
34 this.CellBuilder('闹铃名称', '闹铃')
35 this.CellBuilder('重复', '不重复')
36 }
37 .borderRadius(16)
38 .clip(true)
39
40 Text('删除闹铃')
41 .width(100)
42 .height(40)
43 .borderRadius(20)
44 .backgroundColor('#c3c4c5')
45 .textAlign(TextAlign.Center)
46 .fontColor('#f00')
47 .opacity(0.3)
48 }
49 .padding(15)
50 }
51 .title('新建闹钟')
52 .titleMode(NavigationTitleMode.Mini)
53 .mode(NavigationMode.Stack)
54 .backgroundColor('#f5f5f5')
55 .menus([
56 { value: '', icon: '/images/ic_confirm.png', action: () => this.submit() }
57 ])
58 }
59}
1import preferences from '@ohos.data.preferences'
2
3export class ClockItem {
4 hour?: number
5 minute?: number
6 id?: string
7 reminderId?: number
8 enabled?: boolean
9}
10
11export class ClockStore {
12
13 getStore() {
14 return preferences.getPreferences(getContext(this), 'clockStore')
15 }
16
17 async addClock(clockItem: ClockItem) {
18 const store = await this.getStore()
19 await store.put(clockItem.id, JSON.stringify(clockItem))
20 await store.flush()
21 }
22
23 async delClock(id: string) {
24 const store = await this.getStore()
25 await store.delete(id)
26 await store.flush()
27 }
28
29 async getAllClock() {
30 const store = await this.getStore()
31 const data = await store.getAll()
32 const list = Object.keys(data).map<ClockItem>(key => {
33 return JSON.parse(data[key])
34 })
35 return list
36 }
37}
1@State
2 clockItem: ClockItem = {}
3
4 // Date 不能直接使用 @State 装饰器
5 @State
6 state: { now: Date } = { now: new Date() }
7 clockStore = new ClockStore()
8
9 async submit() {
10
11 // 1. 开启提醒
12 const hour = this.state.now.getHours()
13 const minute = this.state.now.getMinutes()
14 const request: reminderAgentManager.ReminderRequestAlarm = {
15 reminderType: reminderAgentManager.ReminderType.REMINDER_TYPE_ALARM,
16 hour,
17 minute,
18 title: '闹钟',
19 ringDuration: 60
20 }
21 const reminderId = await reminderAgentManager.publishReminder(request)
22 // 2. 记录数据
23 this.clockItem = {
24 hour,
25 minute,
26 id: util.generateRandomUUID(),
27 reminderId,
28 enabled: true
29 }
30 await this.clockStore.addClock(this.clockItem)
31 promptAction.showToast({ message: '添加闹钟成功' })
32 router.back()
33 }
1TimePicker({
2 selected: this.state.now
3 })
4 .borderRadius(16)
5 .clip(true)
1) 获取首选项闹钟数据
1@State
2 clockList: ClockItem[] = []
3
4 clockStore = new ClockStore()
5
6 aboutToAppear() {
7 this.initData()
8 }
9 onPageShow() {
10 this.initData()
11 }
12 async initData() {
13 this.clockList = await this.clockStore.getAllClock()
14 }
2) 遍历数组
1ForEach(this.clockList, (item: ClockItem) => {
2 ClockItemComp({ item })
3 .onClick(() => {
4 router.pushUrl({
5 url: 'pages/DetailPage',
6 params: item
7 })
8 })
9 })
3) 去闹钟项组件渲染
1@State
2 item: ClockItem = {}
3
4 padZero(val: number = 0) {
5 return val.toString().padStart(2, '0')
6 }
1Row({ space: 5 }) {
2 Text(this.item.hour > 12 ? '下午' : '上午')
3 .fontColor('#666')
4 Text(`${this.padZero(this.item.hour > 12 ? this.item.hour - 12 : this.item.hour)}:${this.padZero(this.item.minute)}`)
5 .fontWeight(600)
6 .fontSize(18)
7 }
传递闹铃数据到详情页,需要接收下
页面上的标题需要判断显示
在 submit 函数中加入编辑逻辑
1)传递闹铃数据到详情页,需要接收下
1aboutToAppear() {
2 const params = router.getParams() as ClockItem
3 if (params && params.id) {
4 this.clockItem = { ...params }
5 this.state.now.setHours(this.clockItem.hour)
6 this.state.now.setMinutes(this.clockItem.minute)
7 }
8 }
2)页面上的标题需要判断显示
1+ .title((this.clockItem.id ? '编辑' : '添加') + '闹钟')
2 .titleMode(NavigationTitleMode.Mini)
3 .mode(NavigationMode.Stack)
3)在 submit 函数中加入编辑逻辑
1// 2. 记录数据
2 if (this.clockItem.id) {
3 this.clockItem.hour = hour
4 this.clockItem.minute = minute
5 this.clockItem.enabled = true
6 // 不加 await 让它异步执行,因为可能存在失效的代理提醒,这样不会阻碍后续逻辑
7 reminderAgentManager.cancelReminder(this.clockItem.reminderId)
8 this.clockItem.reminderId = reminderId
9 await this.clockStore.addClock(this.clockItem)
10 promptAction.showToast({ message:'编辑闹钟成功' })
11 } else {
12 this.clockItem = {
13 hour,
14 minute,
15 id: util.generateRandomUUID(),
16 reminderId,
17 enabled: true
18 }
19 await this.clockStore.addClock(this.clockItem)
20 promptAction.showToast({ message:'添加闹钟成功' })
21 }
删除按钮在编辑条件下展示,绑定事件函数
实现删除功能
1)删除按钮在编辑条件下展示,绑定事件函数
1if ( this.clockItem.id ) {
2 Text('删除闹铃')
3 .width(100)
4 .height(40)
5 .borderRadius(20)
6 .backgroundColor('#c3c4c5')
7 .textAlign(TextAlign.Center)
8 .fontColor('#f00')
9 .opacity(0.3)
10 .onClick(() => {
11 this.remove()
12 })
13 }
2)实现删除功能
1async remove () {
2 try {
3 await this.clockStore.delClock(this.clockItem.id)
4 promptAction.showToast({ message: '删除闹钟成功' })
5 // 不加 await 让它异步执行,因为可能存在失效的代理提醒,这样不会阻碍跳转
6 reminderAgentManager.cancelReminder(this.clockItem.reminderId)
7 router.back()
8 } catch (e) {
9 console.error('CLOCK-REMOVE', e.message)
10 }
11 }
1)加入唤起配置,加入延时和关闭配置
1// 跳转
2 wantAgent: {
3 pkgName: 'com.itcast.myapplication',
4 abilityName: 'EntryAbility'
5 },
6 // 操作按钮
7 actionButton: [
8 { title: '关闭', type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_CLOSE },
9 { title: '延时提醒', type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_SNOOZE }
10 ],
11 snoozeTimes: 1,
12 timeInterval: 10 * 60
2)抽取创建后台代理工具类
1import reminderAgentManager from '@ohos.reminderAgentManager'
2export class AlarmManager {
3
4 // 添加代理提醒
5 static async addReminder (hour: number, minute: number) {
6 // 1. 添加后台代理提醒-闹钟
7 const reminderRequest: reminderAgentManager.ReminderRequestAlarm = {
8 reminderType: reminderAgentManager.ReminderType.REMINDER_TYPE_ALARM,
9 hour,
10 minute,
11 ringDuration: 60,
12 title: '闹铃',
13 // 跳转
14 wantAgent: {
15 pkgName: 'com.itcast.hmday05',
16 abilityName: 'EntryAbility'
17 },
18 // 延时和关闭
19 actionButton: [
20 { title: '关闭', type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_CLOSE },
21 { title: '延时提醒', type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_SNOOZE }
22 ],
23 snoozeTimes: 2,
24 timeInterval: 10 * 60
25 }
26
27 const reminderId = await reminderAgentManager.publishReminder(reminderRequest)
28 return reminderId
29 }
30}
3)进行复用
1// 1. 开启提醒
2 const hour = this.state.now.getHours()
3 const minute = this.state.now.getMinutes()
4+ const reminderId = await AlarmManager.addReminder(hour, minute)
5 // 2. 记录数据
1clockStore = new ClockStore()
2
3 async toggle(isOn: boolean) {
4 reminderAgentManager.cancelReminder(this.item.reminderId)
5
6 this.item.enabled = isOn
7 if (this.item.enabled) {
8 const reminderId = await AlarmManager.createAlarmTask(this.item.hour, this.item.minute)
9 this.item.reminderId = reminderId
10 }
11 this.clockStore.addClock(this.item)
12 promptAction.showToast({ message: isOn ? '已开启' : '已关闭' })
13 }
1// 开关
2 Toggle({ type: ToggleType.Switch, isOn: this.item.enabled })
3 .onChange(isOn => this.toggle(isOn))