04-UI组件介绍和实际应用(下)
通过前几章的学习,我们已经对 OpenHarmony 的一些基础组件和布局方式有了初步的了解。在本章中,我们将结合多个组件的使用,通过一个数字时钟的完整示例,进一步巩固学习的内容。 本示例会展示如何使用 OpenHarmony 的动画功能、状态管理,以及滑动条和切换开关等组件,帮助您更好地理解和应用 ArkUI 框架。
1、示例演示
经过前几章的学习,我们对一些基本的组件也有大概的一些了解,若想了解更多可以到鸿蒙官网了解更多
小技巧
我们将实现一个动态数字时钟,时钟能够显示实时更新的时间,并包含以下:
核心功能: 时间动态更新:通过动画实现数字的翻页效果。 亮度调节:使用滑动条组件动态设置屏幕亮度。 全屏模式切换:使用开关组件实现全屏模式和常规模式的切换。 关键组件:
Text:用于显示时钟数字。 Slider:滑动条,用于调整屏幕亮度。 Toggle:开关,用于全屏切换功能。 动画功能:实现数字翻页效果。
1.1、数字闹钟主要部分代码:
1 //修改时间 2 changeTime(): Array<number> { 3 const time = new Date() 4 const hour = time.getHours() 5 const hourOne = Math.floor(hour / 10) 6 const hourTwo = hour % 10 7 const minutesOne = Math.floor(time.getMinutes() / 10) 8 const minutesTwo = time.getMinutes() % 10 9 const secondsOne = Math.floor(time.getSeconds() / 10) 10 const secondsTwo = time.getSeconds() % 10 11 return [hourOne, hourTwo, minutesOne, minutesTwo, secondsOne, secondsTwo] 12 } 13 14 @Builder box(num : number) { 15 Column() { 16 Divider() 17 .zIndex(5) 18 .strokeWidth(2) 19 .color(Color.White) 20 .position({ x: 0, y: '50%' }) 21 22 Text(`${this.timeOne[num]}`) 23 .zIndex(1) 24 .height(108) 25 .width('100%') 26 .borderRadius(8) 27 .fontWeight(700) 28 .padding({ top: 0 }) 29 .fontSize(90) 30 .position({ x: 0, y: 0 }) 31 .fontColor(Color.White) 32 .fontFamily('Monospace') 33 .backgroundColor($r('app.color.text_bg')) 34 .textAlign(TextAlign.Center) 35 36 Text(`${this.timeTwo[num]}`) 37 .zIndex(2) 38 .height(64) 39 .width('100%') 40 .fontWeight(700) 41 .borderRadius(8) 42 .padding({ top: 3 }) 43 .fontSize(90) 44 .position({ x: 0, y: 0 }) 45 .fontColor(Color.White) 46 .fontFamily('Monospace') 47 .backgroundColor($r('app.color.text_bg')) 48 .textAlign(TextAlign.Center) 49 50 Text(`${this.timeThree[num]}`) 51 .zIndex(4) 52 .height(64) 53 .width('100%') 54 .fontWeight(700) 55 .borderRadius(8) 56 .padding({ top: 3 }) 57 .fontSize(90) 58 .position({ x: 0, y: 0 }) 59 .fontColor(Color.White) 60 .fontFamily('Monospace') 61 .textAlign(TextAlign.Center) 62 .backgroundColor($r('app.color.text_bg')) 63 .rotate({ 64 x: 1, 65 y: 0, 66 z: 0, 67 centerX: '50%', 68 centerY: '100%', 69 angle: this.angleOne[num] 70 }) 71 72 Text(`${this.timeFour[num]}`) 73 .zIndex(3) 74 .height(108) 75 .width('100%') 76 .fontWeight(700) 77 .borderRadius(8) 78 .padding({ top: 0 }) 79 .fontSize(90) 80 .position({ x: 0, y: 0 }) 81 .fontColor(Color.White) 82 .fontFamily('Monospace') 83 .backgroundColor($r('app.color.text_bg')) 84 .textAlign(TextAlign.Center) 85 .rotate({ 86 x: 1, 87 y: 0, 88 z: 0, 89 centerX: '50%', 90 centerY: '50%', 91 angle: this.angleTwo[num] 92 }) 93 } 94 .height(108) 95 .width('50%') 96 }
1.2、动画旋转部分代码:
1 animationOne(i : number): void { 2 animateTo({ 3 duration: 250, 4 delay: 0, 5 iterations: 1, 6 onFinish: () => { 7 this.animationTwo(i) 8 this.angleOne[i] = 0 9 } 10 }, () => this.angleOne[i] = 90) 11 } 12 13 animationTwo(i : number): void { 14 animateTo({ 15 duration: 250, 16 delay: 0, 17 iterations: 1, 18 onFinish: () => { 19 this.angleTwo[i] = -90 20 } 21 }, () => this.angleTwo[i] = 0) 22 }
1.3、全屏部分代码:
1 this.isFullScreen = !this.isFullScreen 2 try { 3 let win = await window.getLastWindow(getContext(this)) 4 let names = this.isFullScreen ? [] : ['status', 'navigation'] 5 await win.setWindowSystemBarEnable(names as Array<'status' | 'navigation'>) 6 }
完整代码展示 :
1 import { brightness } from '@kit.BasicServicesKit'; 2 import { LockSwitch } from './LockSwitch'; 3 import { window } from '@kit.ArkUI'; 4 5 @Entry 6 @Component 7 struct Index { 8 @State message: string = 'Hello World'; 9 @State timeOne: Array<number> = [] 10 @State timeTwo: Array<number> = [] 11 @State timeThree: Array<number> = [] 12 @State timeFour: Array<number> = [] 13 @State angleOne: Array<number> = [0, 0, 0, 0, 0, 0] 14 @State angleTwo: Array<number> = [-90, -90, -90, -90, -90, -90] 15 16 @State isFullScreen: boolean = false 17 @State inSetValue: number = 40 18 19 20 aboutToAppear() { 21 const arr = this.changeTime() 22 this.timeOne = [...arr] 23 this.timeTwo = [...arr] 24 this.timeThree = [...arr] 25 this.timeFour = [...arr] 26 setInterval(() => { 27 const time = new Date() 28 if (this.timeOne[5] != time.getSeconds() % 10) { 29 const arr = this.changeTime() 30 for (let i = 0;i < 6; i++) { 31 if (arr[i] != this.timeFour[i]) { 32 this.timeFour[i] = arr[i] 33 this.animationOne(i) 34 setTimeout(() => { 35 this.timeTwo[i] = arr[i] 36 }, 100) 37 setTimeout(() => { 38 this.timeThree[i] = arr[i] 39 }, 150) 40 setTimeout(() => { 41 this.timeOne[i] = arr[i] 42 }, 240) 43 } 44 } 45 } 46 }, 1000) 47 } 48 49 animationOne(i : number): void { 50 animateTo({ 51 duration: 250, 52 delay: 0, 53 iterations: 1, 54 onFinish: () => { 55 this.animationTwo(i) 56 this.angleOne[i] = 0 57 } 58 }, () => this.angleOne[i] = 90) 59 } 60 61 animationTwo(i : number): void { 62 animateTo({ 63 duration: 250, 64 delay: 0, 65 iterations: 1, 66 onFinish: () => { 67 this.angleTwo[i] = -90 68 } 69 }, () => this.angleTwo[i] = 0) 70 } 71 72 setBrightness(): void { 73 brightness.setValue(this.inSetValue) 74 } 75 76 //修改时间 77 changeTime(): Array<number> { 78 const time = new Date() 79 const hour = time.getHours() 80 const hourOne = Math.floor(hour / 10) 81 const hourTwo = hour % 10 82 const minutesOne = Math.floor(time.getMinutes() / 10) 83 const minutesTwo = time.getMinutes() % 10 84 const secondsOne = Math.floor(time.getSeconds() / 10) 85 const secondsTwo = time.getSeconds() % 10 86 return [hourOne, hourTwo, minutesOne, minutesTwo, secondsOne, secondsTwo] 87 } 88 89 @Builder box(num : number) { 90 Column() { 91 Divider() 92 .zIndex(5) 93 .strokeWidth(2) 94 .color(Color.White) 95 .position({ x: 0, y: '50%' }) 96 97 Text(`${this.timeOne[num]}`) 98 .zIndex(1) 99 .height(108) 100 .width('100%') 101 .borderRadius(8) 102 .fontWeight(700) 103 .padding({ top: 0 }) 104 .fontSize(90) 105 .position({ x: 0, y: 0 }) 106 .fontColor(Color.White) 107 .fontFamily('Monospace') 108 .backgroundColor($r('app.color.text_bg')) 109 .textAlign(TextAlign.Center) 110 111 Text(`${this.timeTwo[num]}`) 112 .zIndex(2) 113 .height(64) 114 .width('100%') 115 .fontWeight(700) 116 .borderRadius(8) 117 .padding({ top: 3 }) 118 .fontSize(90) 119 .position({ x: 0, y: 0 }) 120 .fontColor(Color.White) 121 .fontFamily('Monospace') 122 .backgroundColor($r('app.color.text_bg')) 123 .textAlign(TextAlign.Center) 124 125 Text(`${this.timeThree[num]}`) 126 .zIndex(4) 127 .height(64) 128 .width('100%') 129 .fontWeight(700) 130 .borderRadius(8) 131 .padding({ top: 3 }) 132 .fontSize(90) 133 .position({ x: 0, y: 0 }) 134 .fontColor(Color.White) 135 .fontFamily('Monospace') 136 .textAlign(TextAlign.Center) 137 .backgroundColor($r('app.color.text_bg')) 138 .rotate({ 139 x: 1, 140 y: 0, 141 z: 0, 142 centerX: '50%', 143 centerY: '100%', 144 angle: this.angleOne[num] 145 }) 146 147 Text(`${this.timeFour[num]}`) 148 .zIndex(3) 149 .height(108) 150 .width('100%') 151 .fontWeight(700) 152 .borderRadius(8) 153 .padding({ top: 0 }) 154 .fontSize(90) 155 .position({ x: 0, y: 0 }) 156 .fontColor(Color.White) 157 .fontFamily('Monospace') 158 .backgroundColor($r('app.color.text_bg')) 159 .textAlign(TextAlign.Center) 160 .rotate({ 161 x: 1, 162 y: 0, 163 z: 0, 164 centerX: '50%', 165 centerY: '50%', 166 angle: this.angleTwo[num] 167 }) 168 } 169 .height(108) 170 .width('50%') 171 } 172 173 build() { 174 Column() { 175 Row() { 176 Row({ space: 2 }) { 177 this.box(0) 178 this.box(1) 179 } 180 .width('30%') 181 .height('30%') 182 183 Image($r('app.media.dot')) 184 .width(20) 185 .height(50) 186 187 Row({ space: 2 }) { 188 this.box(2) 189 this.box(3) 190 } 191 .width('30%') 192 .height('30%') 193 194 Image($r('app.media.dot')) 195 .width(20) 196 .height(50) 197 198 Row({ space: 2 }) { 199 this.box(4) 200 this.box(5) 201 } 202 .width('30%') 203 .height('30%') 204 } 205 .id('currentTimeBox') 206 .width('50%') 207 .height('50%') 208 209 210 Column({ space: 10 }) { 211 Divider() 212 .strokeWidth(5) 213 .color($r('app.color.divider_bg')) 214 215 Row() { 216 Text($r("app.string.fullScreen")).fontSize(18) 217 218 Blank() 219 220 Toggle({ type: ToggleType.Switch, isOn: this.isFullScreen }) 221 .switchPointColor(0xe5ffffff) 222 .onChange(async () => { 223 this.isFullScreen = !this.isFullScreen 224 try { 225 let win = await window.getLastWindow(getContext(this)) 226 let names = this.isFullScreen ? [] : ['status', 'navigation'] 227 await win.setWindowSystemBarEnable(names as Array<'status' | 'navigation'>) 228 } catch (err) { 229 console.info(`setFullScreen fail, code = ${err.code}`) 230 } 231 }) 232 } 233 .width('90%') 234 .height(62) 235 .borderRadius(24) 236 .margin({ top: 10 }) 237 .backgroundColor(Color.White) 238 .padding({ left: '3%', right: '3%' }) 239 240 Divider() 241 .strokeWidth(5) 242 .color($r('app.color.divider_bg')) 243 244 Row() { 245 Lock() 246 } 247 .width('90%') 248 .height(62) 249 .borderRadius(24) 250 .margin({ top: 10 }) 251 .backgroundColor(Color.White) 252 .padding({ left: '3%', right: '3%' }) 253 254 Divider() 255 .strokeWidth(5) 256 .color($r('app.color.divider_bg')) 257 258 Row() { 259 Text($r("app.string.brightness")) 260 .fontSize(18) 261 262 Slider({ 263 value: this.inSetValue, 264 min: 0, 265 max: 255, 266 step: 5, 267 style: SliderStyle.OutSet 268 }) 269 .id('brightness') 270 .width('90%') 271 .showTips(false) 272 .showSteps(false) 273 .blockColor(0xCCCCCC) 274 .trackColor(Color.Black) 275 .selectedColor(0xCCCCCC) 276 .onChange((value: number, mode: SliderChangeMode) => { 277 this.inSetValue = value 278 this.setBrightness() 279 }) 280 } 281 .width('90%') 282 .height(62) 283 .borderRadius(24) 284 .margin({ top: 10 }) 285 .backgroundColor(Color.White) 286 .padding({ left: '3%', right: '3%' }) 287 288 Divider() 289 .strokeWidth(5) 290 .color($r('app.color.divider_bg')) 291 } 292 .height('100%') 293 294 } 295 .width('100%') 296 .height('100%') 297 .backgroundColor('#F1F3F5') 298 .justifyContent(FlexAlign.Center) 299 } 300 } 301 302 @Component 303 struct Lock { 304 @State isComTime: boolean = true 305 306 build() { 307 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 308 Column() { 309 LockSwitch({ isComTime: $isComTime }) 310 } 311 .width('100%') 312 } 313 } 314 }
源码地址 :示例源码