HOME
  • GM-3568JHF
  • M4-R1
  • M5-R1
  • SC-3568HA
  • M-K1HSE
  • CF-NRS1
  • CF-CRA2
  • 1684XB-32T
  • 1684X-416T
  • C-3568BQ
  • C-3588LQ
  • GC-3568JBAF
  • C-K1BA
Shop
  • English
  • 简体中文
HOME
  • GM-3568JHF
  • M4-R1
  • M5-R1
  • SC-3568HA
  • M-K1HSE
  • CF-NRS1
  • CF-CRA2
  • 1684XB-32T
  • 1684X-416T
  • C-3568BQ
  • C-3588LQ
  • GC-3568JBAF
  • C-K1BA
Shop
  • English
  • 简体中文
  • M4-R1

    • Introduction

      • M4-R1 Introduction
    • Get started quickly

      • OpenHarmony概述
      • 镜像烧录
      • 开发环境准备
      • Hello World应用以及部署
    • Application Development

      • getting Started

        • 第一章 ArkTS语言简介
        • 第二章 UI组件介绍和实际应用(上)
        • 第三章 UI组件介绍和实际应用(中)
        • 第四章 UI组件介绍和实际应用(下)
      • Advanced

        • 第一章 入门指引
        • 第二章 三方库的引用和使用
        • 第三章 应用编译以及部署
        • 第四章 命令行恢复出厂设置
        • 第五章 系统调试--HDC调试
        • 第六章 APP 稳定性测试
        • 第七章 应用测试
    • Equipment Development

      • 第一章 环境搭建
      • 第二章 下载源码
      • 第三章 编译源码
    • Peripherals and interfaces

      • 树莓派接口
      • GPIO 接口
      • I2C 接口
      • SPI通信
      • PWM控制
      • 串口通讯
      • TF Card
      • 屏幕
      • 触摸
      • 音频
      • RTC
      • Ethernet
      • M.2
      • MINI-PCIE
      • Camera
      • WIFI&BT
      • 树莓派拓展板
    • Frequently asked questions

      • 资源下载
  • M5-R1

    • Introduction

      • Introduction to ShimetaPi M5-R1

第四章 UI组件介绍和实际应用(下)

通过前几章的学习,我们已经对 OpenHarmony 的一些基础组件和布局方式有了初步的了解。在本章中,我们将结合多个组件的使用,通过一个数字时钟的完整示例,进一步巩固学习的内容。本示例会展示如何使用 OpenHarmony 的动画功能、状态管理,以及滑动条和切换开关等组件,帮助您更好地理解和应用 ArkUI 框架。

1. 示例演示

经过前几章的学习,我们对一些基本的组件也有大概的一些了解,若想了解更多可以到鸿蒙官网了解更多

Tips

鸿蒙官网

我们将实现一个动态数字时钟,时钟能够显示实时更新的时间,并包含以下:

核心功能:时间动态更新:通过动画实现数字的翻页效果。亮度调节:使用滑动条组件动态设置屏幕亮度。全屏模式切换:使用开关组件实现全屏模式和常规模式的切换。关键组件:

Text:用于显示时钟数字。Slider:滑动条,用于调整屏幕亮度。Toggle:开关,用于全屏切换功能。动画功能:实现数字翻页效果。

TOOL

1.1 数字闹钟主要部分代码:

    //修改时间
	changeTime(): Array<number> {
		const time = new Date()
		const hour = time.getHours()
		const hourOne = Math.floor(hour / 10)
		const hourTwo = hour % 10
		const minutesOne = Math.floor(time.getMinutes() / 10)
		const minutesTwo = time.getMinutes() % 10
		const secondsOne = Math.floor(time.getSeconds() / 10)
		const secondsTwo = time.getSeconds() % 10
		return [hourOne, hourTwo, minutesOne, minutesTwo, secondsOne, secondsTwo]
	}

	@Builder box(num : number) {
		Column() {
		Divider()
			.zIndex(5)
			.strokeWidth(2)
			.color(Color.White)
			.position({ x: 0, y: '50%' })

		Text(`${this.timeOne[num]}`)
			.zIndex(1)
			.height(108)
			.width('100%')
			.borderRadius(8)
			.fontWeight(700)
			.padding({ top: 0 })
			.fontSize(90)
			.position({ x: 0, y: 0 })
			.fontColor(Color.White)
			.fontFamily('Monospace')
			.backgroundColor($r('app.color.text_bg'))
			.textAlign(TextAlign.Center)

		Text(`${this.timeTwo[num]}`)
			.zIndex(2)
			.height(64)
			.width('100%')
			.fontWeight(700)
			.borderRadius(8)
			.padding({ top: 3 })
			.fontSize(90)
			.position({ x: 0, y: 0 })
			.fontColor(Color.White)
			.fontFamily('Monospace')
			.backgroundColor($r('app.color.text_bg'))
			.textAlign(TextAlign.Center)

		Text(`${this.timeThree[num]}`)
			.zIndex(4)
			.height(64)
			.width('100%')
			.fontWeight(700)
			.borderRadius(8)
			.padding({ top: 3 })
			.fontSize(90)
			.position({ x: 0, y: 0 })
			.fontColor(Color.White)
			.fontFamily('Monospace')
			.textAlign(TextAlign.Center)
			.backgroundColor($r('app.color.text_bg'))
			.rotate({
			x: 1,
			y: 0,
			z: 0,
			centerX: '50%',
			centerY: '100%',
			angle: this.angleOne[num]
			})

		Text(`${this.timeFour[num]}`)
			.zIndex(3)
			.height(108)
			.width('100%')
			.fontWeight(700)
			.borderRadius(8)
			.padding({ top: 0 })
			.fontSize(90)
			.position({ x: 0, y: 0 })
			.fontColor(Color.White)
			.fontFamily('Monospace')
			.backgroundColor($r('app.color.text_bg'))
			.textAlign(TextAlign.Center)
			.rotate({
			x: 1,
			y: 0,
			z: 0,
			centerX: '50%',
			centerY: '50%',
			angle: this.angleTwo[num]
			})
		}
		.height(108)
		.width('50%')
	}

1.2 动画旋转部分代码:

		animationOne(i : number): void {
		animateTo({
		duration: 250,
		delay: 0,
		iterations: 1,
		onFinish: () => {
			this.animationTwo(i)
			this.angleOne[i] = 0
		}
		}, () => this.angleOne[i] = 90)
	}

	animationTwo(i : number): void {
		animateTo({
		duration: 250,
		delay: 0,
		iterations: 1,
		onFinish: () => {
			this.angleTwo[i] = -90
		}
		}, () => this.angleTwo[i] = 0)
	}

1.3 全屏部分代码:

	this.isFullScreen = !this.isFullScreen
		try {
			let win = await window.getLastWindow(getContext(this))
			let names = this.isFullScreen ? [] : ['status', 'navigation']
			await win.setWindowSystemBarEnable(names as Array<'status' | 'navigation'>)
			}

完整代码展示 :

	import { brightness } from '@kit.BasicServicesKit';
	import { LockSwitch } from './LockSwitch';
	import { window } from '@kit.ArkUI';

	@Entry
	@Component
	struct Index {
	@State message: string = 'Hello World';
	@State timeOne: Array<number> = []
	@State timeTwo: Array<number> = []
	@State timeThree: Array<number> = []
	@State timeFour: Array<number> = []
	@State angleOne: Array<number> = [0, 0, 0, 0, 0, 0]
	@State angleTwo: Array<number> = [-90, -90, -90, -90, -90, -90]

	@State isFullScreen: boolean = false
	@State inSetValue: number = 40


	aboutToAppear() {
		const arr = this.changeTime()
		this.timeOne = [...arr]
		this.timeTwo = [...arr]
		this.timeThree = [...arr]
		this.timeFour = [...arr]
		setInterval(() => {
		const time = new Date()
		if (this.timeOne[5] != time.getSeconds() % 10) {
			const arr = this.changeTime()
			for (let i = 0;i < 6; i++) {
			if (arr[i] != this.timeFour[i]) {
				this.timeFour[i] = arr[i]
				this.animationOne(i)
				setTimeout(() => {
				this.timeTwo[i] = arr[i]
				}, 100)
				setTimeout(() => {
				this.timeThree[i] = arr[i]
				}, 150)
				setTimeout(() => {
				this.timeOne[i] = arr[i]
				}, 240)
			}
			}
		}
		}, 1000)
	}

	animationOne(i : number): void {
		animateTo({
		duration: 250,
		delay: 0,
		iterations: 1,
		onFinish: () => {
			this.animationTwo(i)
			this.angleOne[i] = 0
		}
		}, () => this.angleOne[i] = 90)
	}

	animationTwo(i : number): void {
		animateTo({
		duration: 250,
		delay: 0,
		iterations: 1,
		onFinish: () => {
			this.angleTwo[i] = -90
		}
		}, () => this.angleTwo[i] = 0)
	}

	setBrightness(): void {
		brightness.setValue(this.inSetValue)
	}

	//修改时间
	changeTime(): Array<number> {
		const time = new Date()
		const hour = time.getHours()
		const hourOne = Math.floor(hour / 10)
		const hourTwo = hour % 10
		const minutesOne = Math.floor(time.getMinutes() / 10)
		const minutesTwo = time.getMinutes() % 10
		const secondsOne = Math.floor(time.getSeconds() / 10)
		const secondsTwo = time.getSeconds() % 10
		return [hourOne, hourTwo, minutesOne, minutesTwo, secondsOne, secondsTwo]
	}

	@Builder box(num : number) {
		Column() {
		Divider()
			.zIndex(5)
			.strokeWidth(2)
			.color(Color.White)
			.position({ x: 0, y: '50%' })

		Text(`${this.timeOne[num]}`)
			.zIndex(1)
			.height(108)
			.width('100%')
			.borderRadius(8)
			.fontWeight(700)
			.padding({ top: 0 })
			.fontSize(90)
			.position({ x: 0, y: 0 })
			.fontColor(Color.White)
			.fontFamily('Monospace')
			.backgroundColor($r('app.color.text_bg'))
			.textAlign(TextAlign.Center)

		Text(`${this.timeTwo[num]}`)
			.zIndex(2)
			.height(64)
			.width('100%')
			.fontWeight(700)
			.borderRadius(8)
			.padding({ top: 3 })
			.fontSize(90)
			.position({ x: 0, y: 0 })
			.fontColor(Color.White)
			.fontFamily('Monospace')
			.backgroundColor($r('app.color.text_bg'))
			.textAlign(TextAlign.Center)

		Text(`${this.timeThree[num]}`)
			.zIndex(4)
			.height(64)
			.width('100%')
			.fontWeight(700)
			.borderRadius(8)
			.padding({ top: 3 })
			.fontSize(90)
			.position({ x: 0, y: 0 })
			.fontColor(Color.White)
			.fontFamily('Monospace')
			.textAlign(TextAlign.Center)
			.backgroundColor($r('app.color.text_bg'))
			.rotate({
			x: 1,
			y: 0,
			z: 0,
			centerX: '50%',
			centerY: '100%',
			angle: this.angleOne[num]
			})

		Text(`${this.timeFour[num]}`)
			.zIndex(3)
			.height(108)
			.width('100%')
			.fontWeight(700)
			.borderRadius(8)
			.padding({ top: 0 })
			.fontSize(90)
			.position({ x: 0, y: 0 })
			.fontColor(Color.White)
			.fontFamily('Monospace')
			.backgroundColor($r('app.color.text_bg'))
			.textAlign(TextAlign.Center)
			.rotate({
			x: 1,
			y: 0,
			z: 0,
			centerX: '50%',
			centerY: '50%',
			angle: this.angleTwo[num]
			})
		}
		.height(108)
		.width('50%')
	}

	build() {
		Column() {
		Row() {
			Row({ space: 2 }) {
			this.box(0)
			this.box(1)
			}
			.width('30%')
			.height('30%')

			Image($r('app.media.dot'))
			.width(20)
			.height(50)

			Row({ space: 2 }) {
			this.box(2)
			this.box(3)
			}
			.width('30%')
			.height('30%')

			Image($r('app.media.dot'))
			.width(20)
			.height(50)

			Row({ space: 2 }) {
			this.box(4)
			this.box(5)
			}
			.width('30%')
			.height('30%')
		}
		.id('currentTimeBox')
		.width('50%')
		.height('50%')


		Column({ space: 10 }) {
			Divider()
			.strokeWidth(5)
			.color($r('app.color.divider_bg'))

			Row() {
			Text($r("app.string.fullScreen")).fontSize(18)

			Blank()

			Toggle({ type: ToggleType.Switch, isOn: this.isFullScreen })
				.switchPointColor(0xe5ffffff)
				.onChange(async () => {
				this.isFullScreen = !this.isFullScreen
				try {
					let win = await window.getLastWindow(getContext(this))
					let names = this.isFullScreen ? [] : ['status', 'navigation']
					await win.setWindowSystemBarEnable(names as Array<'status' | 'navigation'>)
				} catch (err) {
					console.info(`setFullScreen fail, code = ${err.code}`)
				}
				})
			}
			.width('90%')
			.height(62)
			.borderRadius(24)
			.margin({ top: 10 })
			.backgroundColor(Color.White)
			.padding({ left: '3%', right: '3%' })

			Divider()
			.strokeWidth(5)
			.color($r('app.color.divider_bg'))

			Row() {
			Lock()
			}
			.width('90%')
			.height(62)
			.borderRadius(24)
			.margin({ top: 10 })
			.backgroundColor(Color.White)
			.padding({ left: '3%', right: '3%' })

			Divider()
			.strokeWidth(5)
			.color($r('app.color.divider_bg'))

			Row() {
			Text($r("app.string.brightness"))
				.fontSize(18)

			Slider({
				value: this.inSetValue,
				min: 0,
				max: 255,
				step: 5,
				style: SliderStyle.OutSet
			})
				.id('brightness')
				.width('90%')
				.showTips(false)
				.showSteps(false)
				.blockColor(0xCCCCCC)
				.trackColor(Color.Black)
				.selectedColor(0xCCCCCC)
				.onChange((value: number, mode: SliderChangeMode) => {
				this.inSetValue = value
				this.setBrightness()
				})
			}
			.width('90%')
			.height(62)
			.borderRadius(24)
			.margin({ top: 10 })
			.backgroundColor(Color.White)
			.padding({ left: '3%', right: '3%' })

			Divider()
			.strokeWidth(5)
			.color($r('app.color.divider_bg'))
		}
		.height('100%')

		}
		.width('100%')
		.height('100%')
		.backgroundColor('#F1F3F5')
		.justifyContent(FlexAlign.Center)
	}
	}

	@Component
	struct Lock {
	@State isComTime: boolean = true

	build() {
		Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
		Column() {
			LockSwitch({ isComTime: $isComTime })
		}
		.width('100%')
		}
	}
	}

源码地址 : 示例源码


Edit this page on GitHub
Last Updated:
Contributors: zwhuang
Prev
第三章 UI组件介绍和实际应用(中)