介紹 本示例介紹通過CustomDialogController類顯示自定義日曆選擇器。 效果圖預覽 使用說明 載入完成後顯示主界面,點當前日期後會彈出日曆選擇器,選擇日期後會關閉彈窗,主頁面日期會變成選定的日期。 實現思路 獲取當前月和下個月的日期信息。源碼參考GetDate.ets。 const ...
介紹
本示例介紹通過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模塊來實現資源的調用。
參考資料
寫在最後
- 如果你覺得這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙:
- 點贊,轉發,有你們的 『點贊和評論』,才是我創造的動力。
- 關註小編,同時可以期待後續文章ing