对于刚刚接触OpenHarmony应用开发的开发者,最快的入门方式就是开发一个简单的应用,下面记录了一个日历应用的开发过程,通过日历应用的开发,来熟悉基本图形的绘制,ArkUI的组件的使用,UI组件生命周期,加深对OpenHarmony应用开发的理解。
eTS语言:基于TypeScript(简称TS)拓展的出来的,是OpenHarmony应用开发语言,使用ArkUI框架提供的组件进行界面开发。
什么是TypeScript:
TypeScript 是微软开发的一个开源的编程语言,是面向对象强类型化的,在 JAVAScript 的基础上引入了静态类型、类、接口的概念。
TypeScript 和 JavaScript 的区别:
自定义组件生命周期函数
自定义组件常用属性
日历一页显示42天,包括上个月、当前月、下个月的天数,上个月和下个月的日期显示灰色,点击日期显示选中效果。
支持选择年份、月份,指定一个日期,获取当前月的天数,根据该月1号在一周中的第几天,获取上个月显示的天数,以及下个月显示的天数。
获取上一个月的天数,根据指定月份的1号在一周的第几天,上月最大天数,计算出上个月天数,以object的形式添加到数组,以便区分,代码如下:
const prevMonthDays = [];
//获取上个月最大天数
let prevLastDay = new Date(year, month-1, 0).getDate();
//获取某月1号所在一周的第几天
let startWeek = new Date(year, month, 1).getDay();
// 上个月的最大天数减去当前月1号所在一周的第几天
for (let i = prevLastDay - startWeek + 1; i <= prevLastDay; i++) {
prevMonthDays.push({
date: new Date(year, month - 1, i),
status: 'prev'
});
}
获取下一个月的天数,根据当前月份的1号在一周的第几天,当前月份的最大天数,计算出下个月天数,以object的形式添加到数组,以便区分,代码如下:
const nextMonthDays = [];
//获取下个月最大天数
let curLastDay = new Date(year, month, 0).getDate();
//获取当前月份1号在一周的第几天
let startWeek = new Date(year, month, 1).getDay();
//一页的天数减去当前月份的天数和上个月的天数
for (let i = 1; i <= 42 - startWeek - curLastDay + 1; i++) {
nextMonthDays.push({
date: new Date(year, month + 1, i),
status: 'next'
});
}
获取当前月的天数,以object的形式添加到数组,以便区分,代码如下:
let curLastDay = new Date(year, month, 0).getDate();
for (let i = 1; i <= curLastDay; i++) {
curMonthDays.push({
date: new Date(year, month, i),
status: 'current'
});
}
屏幕适配需要用到媒体查询的接口,可以根据设备参数,例如:屏幕分辨率、横竖屏切换来修改应用的样式。
首先导入媒体查询模块:
import mediaquery from '@ohos.mediaquery'
然后通过matchMediaSync接口设置媒体查询条件,并保存返回的条件监听句柄,例如:监听设备类型,横竖屏状态。
//监听横竖屏状态
private listener: mediaquery.MediaQueryListener = mediaquery.matchMediaSync('(orientation: landscape)');
//监听当前设备类型
private deviceListener: mediaquery.MediaQueryListener = mediaquery.matchMediaSync('screen and (device-type: default)');
定义触发回调函数,当匹配到媒体查询条件时会触发此回调函数。
onOrientationChange = (mediaQueryResult) => {
if (mediaQueryResult.matches) {
this.calendarWidth = "70%"
this.titleBarLeft = 80
} else {
this.calendarWidth = "100%"
this.titleBarLeft = 20
}
}
onDeviceTypeChange = (mediaQueryResult) => {
if(mediaQueryResult.matches){
this.titleBarLeftTop = 10
this.weekHeight = 30
this.pikerDialogHeight = 200
console.log("onDeviceTypeChange device-type: default")
}else{
this.titleBarLeftTop = 40
this.weekHeight = 50
this.pikerDialogHeight = 280
}
}
通过条件监听句柄去注册回调函数,在 aboutToAppear 组件初始化的时候执行注册,退出时销毁监听。
//组件初始化
aboutToAppear() {
this.listener.on('change', this.onOrientationChange);
}
//组件销毁
aboutToDisappear(){
this.listener.off('change', this.onOrientationChange);
}
当列表加载的数据过大时,直接采用循环渲染方式,导致页面启动时间过长,可以使用LazyForEach组件进行数据的懒加载进行优化,按需加载数据并创建相应组件。
定义一个类并实现IDataSource接口:
export class YearData implements IDataSource{
private list: number[] = []
private listener: DataChangeListener
constructor(list: number[]) {
this.list = list
}
totalCount(): number {
return this.list.length
}
getData(index: number): any {
return this.list[index]
}
getDatAIndex(data:any){
return this.list.indexOf(data)
}
registerDataChangeListener(listener: DataChangeListener): void {
this.listener = listener
}
unregisterDataChangeListener() {
}
}
在页面中导入并使用。
import { YearData } from '../datasource/YearData'
private data: YearData = new YearData([])
LazyForEach(this.data, (item: string) => {
ListItem() {
Row() {
Text(item).fontSize(20).margin({ left: 10 })
}
}
.onClick(() => {
this.data.pushData('item value: ' + this.data.totalCount())
})
}, item => item)
}
日历应用实现在一页42个格子上显示上个月、当前月、下个月的日期,通过日历应用的开发了解到了ArkUI组件的一些用法,生命周期和数据的加载过程,对之后的应用开发有很大的帮助。
想了解更多关于开源的内容,请访问:
51CTO 鸿蒙开发者社区
https://ost.51cto.com