首页/新闻资讯/正文详情

HarmonyOs应用《重要日》开发第12篇 - 月视图日历组件详解

发布时间:2026/11/15 6:15:05 来源:云帆数科 栏目:资讯中心
HarmonyOs应用《重要日》开发第12篇 - 月视图日历组件详解
本文深入解析 ImportantDays 项目中最复杂的 UI 组件MonthWeekCalendar包括其组件参数设计、月视图网格渲染、日期项的选中/今天/重要日标记逻辑、周视图渲染、无限滚动的联动处理以及日期文字颜色的多级优先策略。一、组件定位MonthWeekCalendar是日历模块的核心 UI 组件负责渲染月视图42 格网格和周视图7 天横排标记今天、选中日期在日期上显示重要日颜色圆点和标题预览处理日期点击事件联动 Swiper 无限滚动二、组件参数设计ComponentV2exportstruct MonthWeekCalendar{Paramvm:CalendarVMCalendarVM.getInstance();ParamonChangeDay:(date:Date)void(){};ParamselectedColor:string#FF6B6B;ParamstartWeekday:number0;ParamisShowHeader:booleantrue;privatemanager:ImportantDayManagerImportantDayManager.getInstance();privateswiperController:SwiperControllernewSwiperController();}参数说明参数类型默认值说明vmCalendarVM单例日历视图模型onChangeDay(date: Date) void空函数日期选择回调selectedColorstring#FF6B6B选中日期的高亮颜色startWeekdaynumber0一周起始日0周日isShowHeaderbooleantrue是否显示星期标题行设计考量vm 通过 Param 传入虽然 vm 是单例但通过Param传入使组件更灵活理论上可传入不同的 VM 实例回调函数模式onChangeDay让父组件决定如何处理日期选择manager 直接引用private manager直接获取单例因为不需要外部控制swiperController 私有Swiper 控制器是组件内部状态三、build 方法整体结构build(){Column(){if(this.isShowHeader){// 星期标题行Row(){ForEach(this.getWeekNames(),(name:string,index:number){Text(name).fontSize(14).fontColor(index0||index6?#FF6B6B:#666666).layoutWeight(1).textAlign(TextAlign.Center)})}.width(100%).padding({top:8,bottom:8})}// 日历主体 - Swiper LazyForEachSwiper(this.swiperController){LazyForEach(this.vm.monthWeekDataSource,(data:DateModelList){Column(){if(this.vm.viewTypeViewTypeEnum.MONTH){this.monthGrid(data)}else{this.weekRow(data)}}},(data:DateModelList,index:number)month_${index})}.cachedCount(CALENDAR_SWIPER_COUNT).index(this.vm.currentSwiperIndex).loop(false).indicator(false).onChange((index:number){this.handleSwiperChange(index);})}.width(100%)}结构层次Column ├── Row (星期标题行) — 条件显示 └── Swiper └── LazyForEach └── Column ├── monthGrid (月视图) — 条件渲染 └── weekRow (周视图) — 条件渲染四、星期标题行privategetWeekNames():string[]{constnames[...WEEK_NAMES];// [日, 一, 二, 三, 四, 五, 六]if(this.startWeekday1){names.push(names.shift()!);// 周一起始[一, 二, 三, 四, 五, 六, 日]}returnnames;}周日/周一起始处理周日起始默认[日, 一, 二, 三, 四, 五, 六]周一起始将 ‘日’ 移到末尾 →[一, 二, 三, 四, 五, 六, 日]周末颜色区分.fontColor(index0||index6?#FF6B6B:#666666)第一个和最后一个周末显示红色工作日显示灰色。五、月视图网格monthGridBuildermonthGrid(data:DateModelList){Grid(){ForEach(data,(dateModel:DateModel,index:number){GridItem(){this.monthDayItem(dateModel)}},(dateModel:DateModel,index:number)${dateModel.dateStr}_${index})}.columnsTemplate(1fr 1fr 1fr 1fr 1fr 1fr 1fr).rowsGap(4).width(100%)}网格配置7 列columnsTemplate(1fr 1fr 1fr 1fr 1fr 1fr 1fr)行间距rowsGap(4)— 4vp 的行间距数据42 个DateModel6行×7列键值${dateModel.dateStr}_${index}— 日期字符串 索引确保唯一六、日期项渲染monthDayItem这是最复杂的 Builder负责单个日期格的完整渲染。BuildermonthDayItem(dateModel:DateModel){Stack({alignContent:Alignment.Center}){// 1. 选中日期的背景圆if(this.vm.isDateSelect(dateModel.dayjsObj)){Circle({width:36,height:36}).fill(this.selectedColor)}// 2. 今天的高亮边框非选中时if(this.vm.isToday(dateModel.dayjsObj)!this.vm.isDateSelect(dateModel.dayjsObj)){Circle({width:36,height:36}).fill(#FFFFFF).stroke(this.selectedColor).strokeWidth(2)}// 3. 内容列Column(){// 日期数字Text(${dateModel.day}).fontSize(16).fontWeight(this.vm.isDateSelect(dateModel.dayjsObj)?FontWeight.Bold:FontWeight.Normal).fontColor(this.getDayTextColor(dateModel))// 重要日标记if(this.hasImportantDay(dateModel)){// 颜色圆点行最多3个Row(){ForEach(this.getImportantDays(dateModel).slice(0,3),(day:ImportantDay){Circle({width:5,height:5}).fill(day.color).margin({right:2})})}.height(6).margin({top:2})// 第一个重要日的标题预览Text(this.getFirstDayShortText(dateModel)).fontSize(8).fontColor(this.getFirstDayColor(dateModel)).maxLines(1).textOverflow({overflow:TextOverflow.Ellipsis}).width(34).textAlign(TextAlign.Center).margin({top:1})}}}.width(100%).height(52).onClick((){this.onDateClick(dateModel);})}渲染层次Stack (居中对齐) ├── Circle (选中背景) — 条件 ├── Circle (今天边框) — 条件 └── Column ├── Text (日期数字) └── Row (重要日标记) — 条件 ├── Row (颜色圆点 × 最多3个) └── Text (标题预览)选中与今天的视觉区分状态视觉表现选中日期实心圆背景 白色粗体数字今天未选中空心圆边框 红色数字今天已选中实心圆背景 白色粗体数字普通日期无装饰 正常颜色数字重要日标记设计颜色圆点最多显示 3 个圆点每个圆点使用重要日的自定义颜色标题预览显示第一个重要日的标题超出宽度时省略字体大小8vp在有限的格子空间内显示更多信息七、日期文字颜色策略privategetDayTextColor(dateModel:DateModel):string{if(this.vm.isDateSelect(dateModel.dayjsObj)){return#FFFFFF;// 选中 → 白色}if(!dateModel.isCurrentMonth){return#CCCCCC;// 非当月 → 灰色}if(this.vm.isToday(dateModel.dayjsObj)){returnthis.selectedColor;// 今天 → 主题色}if(this.hasImportantDay(dateModel)){returnthis.getFirstDayColor(dateModel);// 有重要日 → 重要日颜色}return#333333;// 普通 → 深灰}优先级链选中 → 非当月 → 今天 → 有重要日 → 普通优先级条件颜色1选中日期#FFFFFF白色2非当月#CCCCCC浅灰3今天selectedColor主题色4有重要日day.color重要日颜色5普通#333333深灰设计考量选中状态优先级最高白色文字配彩色背景最清晰非当月优先于今天/重要日避免非当月的今天造成混淆。八、周视图weekRowBuilderweekRow(data:DateModelList){Row(){ForEach(data,(dateModel:DateModel,index:number){Column(){Text(${dateModel.day}).fontSize(16).fontWeight(this.vm.isDateSelect(dateModel.dayjsObj)?FontWeight.Bold:FontWeight.Normal).fontColor(this.getDayTextColor(dateModel))if(this.hasImportantDay(dateModel)){Circle({width:5,height:5}).fill(this.getFirstDayColor(dateModel)).margin({top:2})}}.layoutWeight(1).height(56).justifyContent(FlexAlign.Center).onClick((){this.onDateClick(dateModel);})})}.width(100%)}与月视图的差异特性月视图周视图布局Grid 7列Row 等分选中背景Circle 填充无仅加粗文字重要日标记圆点 标题预览仅圆点高度52vp56vp周视图更简洁适合快速浏览一周概况。九、日期点击处理privateonDateClick(dateModel:DateModel):void{this.vm.changeDate(dateModel.dayjsObj);this.onChangeDay(dateModel.dayjsObj.toDate());}点击日期时更新 VM 中的选中日期触发外部回调通知父组件十、Swiper 切换联动privatehandleSwiperChange(index:number):void{this.vm.currentSwiperIndexindex;this.vm.handleHorizontalSwiper(index);constcurrentDatathis.vm.monthWeekDataSource.getData(index);if(currentDatacurrentData.length15){constmiddleDatecurrentData[15].dayjsObj;if(!this.vm.selectDate.isSame(middleDate,month)){this.vm.selectDatemiddleDate;}}}联动逻辑更新当前 Swiper 索引调用 VM 处理边界追加更新选中日期到当前月份取索引15的日期作为月份参考十一、重要日查询方法privatehasImportantDay(dateModel:DateModel):boolean{returnthis.manager.hasImportantDay(dateModel.dateStr);}privategetImportantDays(dateModel:DateModel):ImportantDay[]{returnthis.manager.getDaysByDate(dateModel.dateStr);}privategetFirstDayColor(dateModel:DateModel):string{constdaysthis.getImportantDays(dateModel);if(days.length0){returndays[0].color;}return#FF6B6B;}privategetFirstDayShortText(dateModel:DateModel):string{constdaysthis.getImportantDays(dateModel);if(days.length0){returndays[0].title;}return;}这些方法封装了对ImportantDayManager的查询提供组件级别的便捷访问。性能考量每次渲染日期项时都会查询dayMap但由于dayMap是Map结构查找复杂度为 O(1)42 个日期格的查询总开销可忽略。十二、总结MonthWeekCalendar是整个项目中 UI 逻辑最密集的组件双视图渲染月视图和周视图通过条件渲染切换多层视觉选中背景、今天边框、重要日标记层层叠加颜色优先级5 级颜色策略确保信息层次清晰事件联动点击和滑动事件与 VM 双向同步性能优化Map 查询 LazyForEach 保证渲染效率这个组件完美展示了 ArkUI 声明式 UI 在复杂交互场景下的表达能力。

相关推荐

PDFsam:开源PDF处理工具如何重塑你的文档工作流
PDFsam:开源PDF处理工具如何重塑你的文档工作流

PDFsam:开源PDF处理工具如何重塑你的文档工作流 【免费下载链接】pdfsam PDFsam, a desktop application to split, merge, mix, rotate PDF files and extract pages 项目地址: https://gitcode.com/gh_mirrors/pd/pdfsam PDFsam(PDF Split and … · 2026/9/22 4:13:37

解锁老旧窗口新生命:Magpie超分辨率工具完全指南
解锁老旧窗口新生命:Magpie超分辨率工具完全指南

解锁老旧窗口新生命:Magpie超分辨率工具完全指南 【免费下载链接】Magpie A general-purpose window upscaler for Windows 10/11. 项目地址: https://gitcode.com/gh_mirrors/mag/Magpie 还在为那些经典游戏或老软件在现代高分辨率显示器上显得模糊而烦恼吗… · 2026/9/21 3:32:00

闲谈《道德经》022|曲全枉直
闲谈《道德经》022|曲全枉直

📑本章摘要 021章阐明 “孔德之容,惟道是从”,探明大道本体恍惚存真,修德根基在于向内求证本源。第二十二章承接体道要义,将天地螺旋闭环的拓扑规律转化为修心、立身、治国全套实操准则。经文以曲、枉、洼、敝、少五大… · 2026/9/6 14:51:56

省外电工证年审证怎么转异地
省外电工证年审证怎么转异地

电工证年审在省外怎么办?学历不高怕报不上名?多久拿证最靠谱? 你是不是也经常听说,电工证是进入工地、电力行业最基本的门槛?可如果你是南阳的应届毕业生,学历不高,想报电工证却担心“报不上名”“拿证时间太长”,这种焦虑真的不是空穴来风。特别是… · 2026/11/15 6:15:04

杏坛考电工证在哪里考网上查询最新政策和避坑指南
杏坛考电工证在哪里考网上查询最新政策和避坑指南

杏坛考电工证在哪里考网上查询最新政策和避坑指南 证书过期了不知道怎么复审延期?你不是一个人,很多人都在找【杏坛考电工证在哪里考】,尤其是像我们信阳浉河区房建工程的从业者,手上拿着电工证,却不知道怎么操作网上查询、复审、继续教育这些流程,一不… · 2026/11/15 6:15:04

沈阳+中级电工证到期换证流程
沈阳+中级电工证到期换证流程

沈阳中级电工证怕考不过白交培训费?良心建议来了 怕考不过白交培训费?这几乎是每个打算报考沈阳中级电工证的人都会担心的问题。尤其是对于那些已经工作多年、想通过考证提升技能和收入的人来说,这笔费用不能随便砸。今天就从一个从业多年的角度来看,给你… · 2026/11/15 6:15:04

审核电工证最新政策解读
审核电工证最新政策解读

三门峡电工证审核避坑指南:你打算先考哪个工种的证?评论区聊聊 证书过期了不知道怎么复审延期,这事儿在咱们三门峡从事电工相关工作的朋友里可太常见了。今天咱们就聊聊 审核电工证 ,特别是郑州报考避坑指南,给大伙儿支个招儿,别再踩雷了。… · 2026/11/15 6:15:04

东台有没有办电工证良心建议全攻略
东台有没有办电工证良心建议全攻略

东台有没有办电工证良心建议全攻略 不知道去哪报名怕被中介坑?东台有没有办电工证?别急,今天这些建议都是从业十年的老手亲测干货,帮你避开那些“坑中坑”,拿到手软的电工证。 东台有没有办电工证?官方渠道在哪里?… · 2026/11/15 6:15:04

浙江电工作业低压模拟怎么考 电子证书怎么查
浙江电工作业低压模拟怎么考 电子证书怎么查

浙江电工作业低压模拟怎么考 电子证书怎么查 之前考的证在外省能不能转过来,这是很多在浙江打工的老电工最关心的问题。现在国家推行电子证书,很多人又担心自己手里那本纸质证是不是还有用,或者能不能顺利转过来。今天我们就来聊聊浙江电工作业低压模拟的… · 2026/11/15 6:14:04

长春初级电工证怎么考?通过率揭秘全在这里
长春初级电工证怎么考?通过率揭秘全在这里

长春初级电工证怎么考?通过率揭秘全在这里 之前考的证在外省能不能转过来?这几乎是每个想从事电工工作的人都会问的问题。特别是那些在外地打拼多年、手里握着一张“外地电工证”的人,到了长春想继续干这一行,第一反应就是“我的证能用吗?”。今天我们就… · 2026/11/15 0:00:50

国内电工证报考条件与考试时间
国内电工证报考条件与考试时间

低压电工证怎么考?学历不高也能报名,官方报名入口全在这 你是不是经常听说“电工证是入行门槛”,但又担心自己学历不够、经验不足,根本报不了名?别急,今天就带你从零了解【国内电工证】的报考流程、考试内容,还有怎么在 官方报名入口… · 2026/11/15 0:00:50

电工作业时如何断电?电子证书到底能不能全国通用?
电工作业时如何断电?电子证书到底能不能全国通用?

电工作业时如何断电?电子证书到底能不能全国通用? 实操考试心里没底怕挂科,特别是电工作业时如何断电这一操作,不仅关系到你能不能拿到证书,更关系到以后能不能顺利上岗。很多人觉得这不过就是“断个电”,但其实这里面的门道可不少,稍有不慎就可能出错… · 2026/11/15 0:00:50

长春初级电工证怎么考?通过率揭秘全在这里
长春初级电工证怎么考?通过率揭秘全在这里

长春初级电工证怎么考?通过率揭秘全在这里 之前考的证在外省能不能转过来?这几乎是每个想从事电工工作的人都会问的问题。特别是那些在外地打拼多年、手里握着一张“外地电工证”的人,到了长春想继续干这一行,第一反应就是“我的证能用吗?”。今天我们就… · 2026/11/15 0:00:50

国内电工证报考条件与考试时间
国内电工证报考条件与考试时间

低压电工证怎么考?学历不高也能报名,官方报名入口全在这 你是不是经常听说“电工证是入行门槛”,但又担心自己学历不够、经验不足,根本报不了名?别急,今天就带你从零了解【国内电工证】的报考流程、考试内容,还有怎么在 官方报名入口… · 2026/11/15 0:00:50

电工作业时如何断电?电子证书到底能不能全国通用?
电工作业时如何断电?电子证书到底能不能全国通用?

电工作业时如何断电?电子证书到底能不能全国通用? 实操考试心里没底怕挂科,特别是电工作业时如何断电这一操作,不仅关系到你能不能拿到证书,更关系到以后能不能顺利上岗。很多人觉得这不过就是“断个电”,但其实这里面的门道可不少,稍有不慎就可能出错… · 2026/11/15 0:00:50

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/15 1:51:20

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/15 4:02:19

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/15 3:02:05

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码