export interface Month { month: string; num: number; days: number[]; } export class MonthDataSource implements IDataSource { private listeners: DataChangeListener[] = []; private dataArray: Month[] = []; public totalCount(): number { return this.dataArray.length; } public getData(index: number): Month { return this.dataArray[index]; } registerDataChangeListener(listener: DataChangeListener): void { if (this.listeners.indexOf(listener) < 0) { console.info('add listener'); this.listeners.push(listener); } } unregisterDataChangeListener(listener: DataChangeListener): void { const pos = this.listeners.indexOf(listener); if (pos >= 0) { console.info('remove listener'); this.listeners.splice(pos, 1); } } notifyDataAdd(index: number): void { this.listeners.forEach(listener => { listener.onDataAdd(index); }) } notifyDataChange(index: number): void { this.listeners.forEach(listener => { listener.onDataChange(index); }) } notifyDataDelete(index: number): void { this.listeners.forEach(listener => { listener.onDataDelete(index); }) } notifyDataMove(from: number, to: number): void { this.listeners.forEach(listener => { listener.onDataMove(from, to); }) } public addData(index: number, data: Month): void { this.dataArray.splice(index, 0, data); this.notifyDataAdd(index); } public pushData(data: Month | Month[]): void { if (Array.isArray(data)) { this.dataArray.push(...data); } else { this.dataArray.push(data); } this.notifyDataAdd(this.dataArray.length - 1); } } 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(); for (let item = 0; item < currentFirstWeekDay; item++) { currentAllDay[item] = 0; } for (let item = 1; item <= totalDays; item++) { currentAllDay.push(item); } for (let item = 0; item < 6 - currentLastWeekDay; item++) { currentAllDay.push(0); } return currentAllDay; } const MONDAY = '一'; const TUESDAY = '二'; const WEDNESDAY = '三'; const THURSDAY = '四'; const FRIDAY = '五'; const SATURDAY = '六'; const SUNDAY = '日'; const MONTHS = 12; const JANUARY = 1; const MONTH_NUMBER = 35; const GRID_HEIGHT_L = 360; const GRID_HEIGHT_M = 300; @Entry @Component struct CustomCalendarPicker { @State contentData: MonthDataSource = new MonthDataSource(); @State date: number[] = []; @State currentDay: number = 1; @State currentMonth: number = 1; @State isSeleted:boolean = false @State isFillColor:boolean = false @State record:number[] = [1,4,8,9,3] @State fillColor:string = '#E5000000' @State currentYear: number = 1; @State currentWeekDay: number = 0; @State currentMonthDay: number[] = []; @State nextMonth: number = 1; @State nextYear: number = 1; @State nextMonthDay: number[] = []; private week: string[] = [SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY]; aboutToAppear(): void { let nowDate = new Date(); this.currentMonth = nowDate.getMonth() + 1; this.currentDay = nowDate.getDate(); this.currentYear = nowDate.getFullYear(); this.currentWeekDay = new Date(this.currentYear, this.currentMonth - 1, this.currentDay).getDay(); this.date.push(this.currentYear) this.date.push(this.currentMonth); this.date.push(this.currentDay); this.date.push(this.currentWeekDay); this.currentMonthDay = getMonthDate(this.currentMonth, this.currentYear); if (this.currentMonth == MONTHS) { this.nextMonth = JANUARY; this.nextYear = this.currentYear + 1; } else { this.nextMonth = this.currentMonth + 1; this.nextYear = this.currentYear; } this.nextMonthDay = getMonthDate(this.nextMonth, this.nextYear); let months: Month[] = [ { month: '', num: this.currentMonth, days: this.currentMonthDay } ] this.contentData.pushData(months); } build() { Column(){ Text(this.date[0] + '-' + this.date[1] +' ^') .fontSize(20) .fontColor(Color.Black) List() { ForEach(this.week, (weekInfomation: string) => { ListItem() { Text(weekInfomation) .textAlign(TextAlign.Center) .width('100%') .height(20) } .width('14.3%') }) } .width('100%') .height(20) .listDirection(Axis.Horizontal) .scrollBar(BarState.Off) List() { LazyForEach(this.contentData, (monthItem: Month) => { ListItemGroup() { ListItem() { Stack() { Grid() { ForEach(monthItem.days, (day: number) => { GridItem() { Column(){ if(day > 0){ Text(day.toString()) .fontSize(20) .fontColor(day < this.currentDay && monthItem.num === this.currentMonth || day == this.currentDay && this.isFillColor ? '#99000000' : this.fillColor) if(day < this.currentDay && monthItem.num === this.currentMonth){ Circle() .width(10) .height(10) .fill((day < this.currentDay && monthItem.num === this.currentMonth || this.isSeleted) && this.record.indexOf(day) >= 0 ? '#4cddd0': '#fc2c4c') }else if(day == this.currentDay && this.isSeleted){ Circle() .width(10) .height(10) .fill('#4cddd0') } } } } .borderRadius(12) }) } .backgroundColor('#FFFFFF') .columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr') .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) } } } }) } .height('50%') .width('100%') .edgeEffect(EdgeEffect.None) .scrollBar(BarState.Off) .sticky(StickyStyle.Header) } } }