1/** 2 * 3 * Copyright (c) 2025 Huawei Device Co., Ltd. 4 * 5 * All rights reserved. 6 * Redistribution and use in source and binary forms, with or without modification, 7 * are permitted provided that the following conditions are met: 8 * 9 * Redistributions of source code must retain the above copyright notice,this 10 * list of conditions and the following disclaimer. 11 * 12 * Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, 17 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, 23 * 24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26import hilog from '@ohos.hilog' 27import { getMonthDate } from './GetDate'; 28import { Month, MonthDataSource } from './MonthDataSource'; 29import { 30 memo, 31 __memo_context_type, 32 __memo_id_type 33} from '@ohos.arkui.stateManagement' // should be insert by ui-plugins 34import { 35 Text, 36 TextAttribute, 37 Column, 38 Component, 39 Button, 40 ButtonAttribute, 41 ClickEvent, 42 UserView, 43 Flex, 44 ItemAlign, 45 ForEach, 46 FlexWrap, 47 Entry, 48 TextAlign, 49 $r, 50 Color, 51 HorizontalAlign, 52 SafeAreaType, 53 Row, 54 LazyForEach, 55 SafeAreaEdge, 56 Span, 57 List, 58 EdgeEffect, 59 BarState, 60 Scroll, 61 Scroller, 62 ExpectedFrameRateRange, 63 ListItem 64} from '@ohos.arkui.component'; // TextAttribute should be insert by ui-plugins 65import { 66 State, 67 Link, 68 StateDecoratedVariable, 69 MutableState, 70 stateOf, 71 observableProxy 72} from '@ohos.arkui.stateManagement'; // should be insert by ui-plugins 73import { Context, UIContext } from '@ohos.arkui.UIContext'; 74 75const MONDAY = '一'; 76const TUESDAY = '二'; 77const WEDNESDAY = '三'; 78const THURSDAY = '四'; 79const FRIDAY = '五'; 80const SATURDAY = '六'; 81const SUNDAY = '日'; 82const WEEK: string[] = [SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY]; // 设置日历周,从周日开始 83const MONTH: string = '月'; 84const YEAR: string = '年'; 85 86/** 87 * 通过组件复用,加载每个月份的数据,当数据量较多时,快速滑动到底部,会出现掉帧的情况。 88 */ 89 90@Component 91export struct ReusePage { 92 @State contentData: MonthDataSource = new MonthDataSource(); // 列表数据 93 nowDate: Date = new Date(); 94 currentMonth: number = this.nowDate.getMonth() + 1; // 当前月份 95 currentDay: number = this.nowDate.getDate(); // 当前日 96 currentYear: number = this.nowDate.getFullYear(); // 当前年份 97 currentWeekDay: number = new Date(this.currentYear, this.currentMonth - 1, this.currentDay).getDay(); // 当前周几 98 private scroller: Scroller = new Scroller(); // 二级列表Scroller对象 99 100 // 初始化日历中一年的数据 101 initCalenderData() { 102 for (let k = this.currentYear; k < 2035; ++k) { 103 for (let i = 1; i <= 12; i++) { 104 // 获取每个月的日数据 105 const monthDays: number[] = getMonthDate(i, k); 106 const month: Month = { 107 month: i + MONTH, 108 num: i, 109 days: monthDays, 110 year: k 111 }; 112 this.contentData.pushData(month); 113 } 114 } 115 } 116 117 aboutToAppear() { 118 this.initCalenderData(); 119 } 120 121 build() { 122 Column() { 123 Text(this.currentYear + YEAR) 124 .width('100%') 125 .height(40) 126 .fontSize(20) 127 .fontColor(Color.Black) 128 .backgroundColor($r('app.color.highlyloadedcomponentrender_color_year_background')) 129 .textAlign(TextAlign.Center) 130 .id('id_highly_loaded_component_render_title') 131 List() { 132 LazyForEach(this.contentData, (monthItem: Month) => { 133 ListItem() { 134 ItemView({ 135 monthItem: monthItem, 136 currentMonth: this.currentMonth, 137 currentDay: this.currentDay, 138 currentYear: this.currentYear 139 }) 140 }.width('100%') 141 }) 142 } 143 .width('100%') 144 } 145 .width('100%') 146 .height('100%') 147 .backgroundColor($r('app.color.ohos_id_color_background')) 148 .alignItems(HorizontalAlign.Center) 149 .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM]) 150 } 151} 152 153// @Reusable 154@Component 155struct ItemView { 156 @State monthItem: Month = { 157 month: '', 158 num: 0, 159 days: [], 160 year: 0 161 } as Month; 162 private currentMonth: number = 0; 163 private currentYear: number = 0; // 当前年份 164 private currentDay: number = 0; 165 private temp: Month[] = new Array<Month>(); 166 private step: number = 0; 167 private maxStep: number = 2; // 最多执行的帧数 168 readonly MAX_EVERY_FRAME: number = 5; // 每帧最多处理的数据量 169 @State month: string = ''; 170 @State monthNumber: number = 0; 171 @State days: number[] = new Array<number>(); 172 @State year: number = 0; 173 174 build() { 175 Flex({ wrap: FlexWrap.Wrap }) { 176 // 月份信息 177 Text(this.monthItem.month) 178 .fontSize(25) 179 .height(40) 180 .fontColor(Color.Black) 181 .width('100%') 182 .textAlign(TextAlign.Start) 183 .layoutWeight(1) 184 185 ForEach(WEEK, (weekday: string) => { 186 Text(weekday) 187 .fontSize(20) 188 .width(50) 189 .height(30) 190 .fontColor(weekday === SUNDAY || weekday === SATURDAY ? Color.Red : Color.Black) 191 .borderRadius(10) 192 .textAlign(TextAlign.Center) 193 .layoutWeight(1) 194 }) 195 // 日期信息 196 ForEach(this.monthItem.days, (day: number, index: number) => { 197 Text() { 198 Span(JSON.stringify(day)) 199 .fontSize(20) 200 } 201 .height(50) 202 .width(50) 203 .opacity(day === 0 ? 0 : 1) 204 .fontColor(Color.Black) 205 .borderRadius(10) 206 .textAlign(TextAlign.Center) 207 .backgroundColor(day === this.currentDay && this.monthItem.num === this.currentMonth && 208 this.monthItem.year === this.currentYear ? 209 $r('app.color.ohos_id_color_palette9') : Color.Transparent) 210 .layoutWeight(1) 211 }) 212 } 213 .alignSelf(ItemAlign.Start) 214 .backgroundColor(Color.Transparent) 215 .width(350) 216 } 217}