介紹
本示例介紹透過CustomDialogController類顯示自定義日曆選擇器。
效果圖預覽
使用說明
- 載入完成後顯示主介面,點當前日期後會彈出日曆選擇器,選擇日期後會關閉彈窗,主頁面日期會變成選定的日期。
實現思路
- 獲取當前月和下個月的日期資訊。原始碼參考GetDate.ets。
const SATURDAY = 6 // 日曆表上週六對應的序列號,從週日開始算起,取值0~6
export function getMonthDate(specifiedMonth: number, specifiedYear: number) {
let currentFirstWeekDay: number = 0; // 初始化指定月的第一天是周幾
let currentLastWeekDay: number = 0; // 初始化指定月的最後一天是周幾
let currentAllDay: number[] = []; // 初始化指定月的日期排列陣列
let totalDays = new Date(specifiedYear, specifiedMonth, 0).getDate(); // 初始化指定月總天數
currentFirstWeekDay = new Date(specifiedYear, specifiedMonth - 1, 1).getDay() // 獲取指定月的第一天是周幾
currentLastWeekDay = new Date(specifiedYear, specifiedMonth - 1, totalDays).getDay() // 獲取指定月的最後一天是周幾
// 將月份中顯示上個月日期的內容置0
for (let item = 0; item < currentFirstWeekDay; item++) {
currentAllDay[item] = 0;
}
// 將本月日期內容存入陣列
for (let item = 1; item <= totalDays; item++) {
currentAllDay.push(item);
}
// 將月份中顯示下個月日期的內容置0
for (let item = 0; item < SATURDAY - currentLastWeekDay; item++) {
currentAllDay.push(0);
}
return currentAllDay;
}
- 透過CustomDialogController類初始化自定義日曆彈窗。原始碼參考CalendarView.ets。
dialogController: CustomDialogController = new CustomDialogController({
builder: CustomCalendarPickerDialog({
date: this.date,
currentMonth: this.currentMonth,
currentDay: this.currentDay,
currentWeekDay: this.currentWeekDay,
currentYear: this.currentYear,
cancel: this.onCancel
}),
alignment: DialogAlignment.Bottom, // 自定義彈窗底端對齊
customStyle: true // 彈窗樣式自定義
})
- 設定自定義日曆選擇器介面。原始碼參考CustomCalendarPickerDialog.ets。
// 每個月的日期
List() {
/*
*效能知識點:列表中資料較多且不確定的情況下,使用LazyForEach進行資料迴圈渲染。
*當元件滑出可視區域外時,框架會進行元件銷燬回收以降低記憶體佔用。
*文件參考連結:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/arkts-rendering-control-lazyforeach-0000001524417213-V2
*/
LazyForEach(this.contentData, (monthItem: Month) => {
// 設定ListItemGroup頭部元件,顯示年份和月份
ListItemGroup({ header: this.itemHead(monthItem.month) }) {
ListItem() {
Stack() {
Text(monthItem.num.toString())
.fontSize($r('app.integer.month_text'))
.fontColor($r('app.color.ohos_id_color_palette_aux8'))
.opacity(MONTH_OPACITY)
Grid() {
ForEach(monthItem.days, (day: number) => {
GridItem() {
Text(day.toString())
.fontSize($r('app.string.ohos_id_text_size_headline'))
.fontColor(day < this.currentDay && monthItem.num ===
this.currentMonth ? $r('app.color.ohos_id_color_text_secondary') : $r('app.color.ohos_id_color_text_primary'))
}
.borderRadius($r('app.string.ohos_id_corner_radius_default_m'))
.backgroundColor(day === this.currentDay && monthItem.num ===
this.currentMonth ? $r('app.color.ohos_id_color_palette9') : $r('app.color.ohos_id_color_background'))
.opacity(day === 0 ? 0 : 1) // 將日期陣列中為0的都設定為不顯示,即不顯示上個月和下個月的內容
// 點選選定的日期後,關閉日曆彈窗,顯示日期改變為選擇的日期
.onClick(() => {
if (day != 0) {
let weekIndex = monthItem.days.indexOf(day) % WEEK_NUMBER; // 將當前日轉換成星期顯示
this.date = [monthItem.num, day, weekIndex];
this.controller.close(); // 關閉自定義彈窗
}
})
})
}
.backgroundColor($r('app.color.ohos_id_color_background'))
.columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr')
// 當前月顯示的陣列元素個數大於35則顯示6行,否則顯示5行
.rowsTemplate(monthItem.days.length > MONTH_NUMBER ? '1fr 1fr 1fr 1fr 1fr 1fr' : '1fr 1fr 1fr 1fr 1fr')
.height(monthItem.days.length > MONTH_NUMBER ? GRID_HEIGHT_L : GRID_HEIGHT_M)
}
}
}
})
}
高效能知識點
本示例使用了LazyForEach進行資料懶載入,List佈局時會根據可視區域按需建立ListItem元件,並在ListItem滑出可視區域外時銷燬以降低記憶體佔用。 LazyForEach:資料懶載入
工程結構&模組型別
customcalendarpickerdialog // har型別
|---components
| |---GetDate.ets // 獲取日期資訊
| |---MonthDataSource.ets // 資料型別定義
|---view
| |---CustomCalendarPickerDialog.ets // 檢視層-自定義日曆
| |---CalendarView.ets // 檢視層-場景主頁面
模組依賴
本例項依賴common模組來實現資源的呼叫。
參考資料
自定義彈窗
LazyForEach:資料懶載入
寫在最後
- 如果你覺得這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙:
- 點贊,轉發,有你們的 『點贊和評論』,才是我創造的動力。
- 關注小編,同時可以期待後續文章ing🚀,不定期分享原創知識。
- 想要獲取更多完整鴻蒙最新VIP學習資源,請移步前往小編:
https://qr21.cn/FV7h05