HarmonyOS NEXT應用開發案例—自定義日曆選擇器

生活就是这么怪發表於2024-04-22

介紹

本示例介紹透過CustomDialogController類顯示自定義日曆選擇器。

效果圖預覽

image

使用說明

  1. 載入完成後顯示主介面,點當前日期後會彈出日曆選擇器,選擇日期後會關閉彈窗,主頁面日期會變成選定的日期。

實現思路

  1. 獲取當前月和下個月的日期資訊。原始碼參考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;
}
  1. 透過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 // 彈窗樣式自定義
})
  1. 設定自定義日曆選擇器介面。原始碼參考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

相關文章