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 在复杂交互场景下的表达能力。

相关新闻

终极指南:5分钟掌握StardewXnbHack游戏文件解包神器

终极指南:5分钟掌握StardewXnbHack游戏文件解包神器

终极指南:5分钟掌握StardewXnbHack游戏文件解包神器 【免费下载链接】StardewXnbHack A simple one-way XNB unpacker for Stardew Valley. 项目地址: https://gitcode.com/gh_mirrors/st/StardewXnbHack 想要深度定制你的星露谷世界吗?StardewXn…

2026/10/8 5:19:32 阅读更多 →
3分钟学会VideoDownloadHelper:你的浏览器视频下载神器

3分钟学会VideoDownloadHelper:你的浏览器视频下载神器

3分钟学会VideoDownloadHelper:你的浏览器视频下载神器 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 还在为网页上的精彩视频无…

2026/10/7 12:50:26 阅读更多 →
IPXWrapper终极指南:让经典游戏在现代Windows上重获网络对战功能

IPXWrapper终极指南:让经典游戏在现代Windows上重获网络对战功能

IPXWrapper终极指南:让经典游戏在现代Windows上重获网络对战功能 【免费下载链接】ipxwrapper 项目地址: https://gitcode.com/gh_mirrors/ip/ipxwrapper 你是否怀念《红色警戒2》、《魔兽争霸II》等经典游戏的局域网对战体验?在现代Windows 10/…

2026/10/7 13:01:44 阅读更多 →

最新新闻

VC++ FTP服务器与客户端完整源码解析:从协议到断点续传实战

VC++ FTP服务器与客户端完整源码解析:从协议到断点续传实战

简介:一套面向VC/MFC与网络通信初学者的FTP客户端与服务器完整示例工程,基于VC6.0调试通过。工程同时提供控制台版本的FTP服务器和MFC界面客户端,源码头文件结构清晰,关键功能均以类接口形式开放,便于在此基础上扩展成…

2026/10/14 5:24:12 阅读更多 →
不做Delta Rule的线性注意力:CyFA结构化累积机制解析与实测

不做Delta Rule的线性注意力:CyFA结构化累积机制解析与实测

1. 从"Delta Rule依赖症"说起:为什么大家默认线性注意力必须做增量更新过去一年,线性注意力这条技术路线几乎被一种共识笼罩:想让模型在长序列上既快又准,就得在状态更新里塞进某种"增量学习"的机制。GDN、KD…

2026/10/14 5:24:12 阅读更多 →
AIGC检测率78%怎么办?2026年教育学专业论文降痕实录

AIGC检测率78%怎么办?2026年教育学专业论文降痕实录

答辩前一周,我把教育学硕士论文初稿扔进AIGC检测系统,屏幕上跳出来的数字是78%。那一刻脑子是懵的——导师前一天刚在群里发通知,检测结果超过30%的一律退回重写。盯着那份标红的报告看了半小时,我才接受一个事实:文献…

2026/10/14 5:24:12 阅读更多 →
自然排序原理与多语言实现:告别文件排序错乱

自然排序原理与多语言实现:告别文件排序错乱

做文件批量导出时,你大概率见过这种场面:同一个目录下明明有 File 1、File 2、File 10,排序结果却是 File 10、File 1、File 2?这种反直觉的顺序,正是缺失自然排序(Natural Sort Order)造成的。…

2026/10/14 5:24:12 阅读更多 →
自然排序详解:解决文件名中数字排序混乱问题

自然排序详解:解决文件名中数字排序混乱问题

1. 问题根源:为什么 File 10 会排到 File 2 前面?1.1 从一次真实的文件整理崩溃说起先说个我上周刚踩过的坑。整理一个素材库,里面是几百个按时间序列导出的截图:File 1.png、File 2.png……一直到 File 120.png。在某个同步盘里打…

2026/10/14 5:24:12 阅读更多 →
2026企业文档协作解决方案与实施指南

2026企业文档协作解决方案与实施指南

1. 企业文档协作的痛点与需求解析在2026年的数字化办公环境中,跨部门文档协作已成为企业运营的基础需求。根据我们团队对327家中大型企业的调研,89%的组织存在"信息孤岛"现象——市场部的方案需要重新排版才能给技术团队参考,财务数…

2026/10/14 5:23:12 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/12 18:11:17 阅读更多 →