在鸿蒙Next中开发一个月历组件
最近一直在出差,工作繁忙,很久没有时间更新文章了,连华为开发者大会也错过了。今天周末,忙里偷闲给大家分享一个鸿蒙月历组件。

这样的组件大家在工作中应该经常会遇到,而鸿蒙又没有提供一个这样的系统组件,今天我们就来看看怎么实现它。
标题部分比较简单,由两个箭头图片和一个文本组件构成,不再赘述。
下面的‘星期’部分有很多方式去实现,这里我选择使用弹性布局Flex:
@State WEEKS:string[] = ['周日','周一','周二','周三','周四','周五','周六']
Flex({direction:FlexDirection.Row,wrap:FlexWrap.NoWrap}){
ForEach(this.WEEKS,(str:string,index)=>{
Text(str)
.fontSize(14)
.fontColor(Color.Gray)
.textAlign(TextAlign.Center)
.width('50%')
.height(35)
})
}
最难的部分在于日历部分,难点在于我们首先要知道当前月份一共有多少天,还要知道从星期几开始排列,也就是这个月的1号是星期几。
在鸿蒙中只需要一行代码就可以获取当前月份的总天数:
const totalDays = new Date(year, month, 0).getDate();
再获取1号是星期几:
currentFirstWeekDay = new Date(year, month - 1, 1).getDay();
接下来,为了方便展示数据,我们除了要把总天数存入数组以外,还要在1号前补0。比如某个月的第一天是星期三,我们就要在前面补两个0,或者你如果把周日放在第一天就要补3个0。
for (let item = 0; item < currentFirstWeekDay; item++) {
currentAllDay.push(0)
}
for (let item = 1; item <= totalDays; item++) {
currentAllDay.push(item);
}
在创建数组的过程,你还可以插入一些其他需要展示的信息。
有了上面的数组之后就可以很容易的展示它们,你可以选择Grid网格组件,也可以使用Flex弹性布局组件:
Flex({direction:FlexDirection.Row,wrap:FlexWrap.Wrap}){
ForEach(this.MONTHDAY,(calendar:Calendar,index)=>{
Column({space:2}){
Text(calendar.day.toString())
.fontSize(16)
.fontColor(Color.Black)
.textAlign(TextAlign.Center)
.fontWeight(FontWeight.Bold)
Text(calendar.content)
.fontColor(Color.Gray)
.fontSize(10)
}
.justifyContent(FlexAlign.Center)
.padding({top:4})
.width('14.2%')
.height(60)
.alignItems(HorizontalAlign.Center)
.visibility(calendar.day == 0? Visibility.Hidden:Visibility.Visible)
.backgroundColor(Color.White)
})
}
下面为大家贴出完整代码:
@Entry
@Component
struct Index {
@State WEEKS:string[] = ['周日','周一','周二','周三','周四','周五','周六']
@State MONTHDAY:Calendar[] = []
@State dateToday:Date = new Date()
@State monthNow:number = this.dateToday.getMonth() + 1
@State yearNow:number = this.dateToday.getFullYear()
aboutToAppear(){
this.getMonthContent()
}
getMonthContent(){
const monthDays: number[] = this.getMonthDate(this.monthNow, this.yearNow);
this.MONTHDAY = []
for (let index = 0; index < monthDays.length; index++) {
const num = monthDays[index];
let calendarItem:Calendar = {
year:this.yearNow,
month:this.monthNow,
day:num,
content:'内容 ' + (Math.floor(Math.random() * 10)).toString()
}
this.MONTHDAY.push(calendarItem)
}
}
getMonthDate(month: number, year: number): number[] {
const SATURDAY: number = 6;
let currentFirstWeekDay: number = 0;
let currentLastWeekDay: number = 0;
const currentAllDay: number[] = [];
const totalDays = new Date(year, month, 0).getDate();
//最后-1表示星期从周一开始,周日开始则不需要
currentFirstWeekDay = new Date(year, month - 1, 1).getDay();
currentLastWeekDay = new Date(year, month - 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 < SATURDAY - currentLastWeekDay; item++) {
currentAllDay.push(0);
}
return currentAllDay;
}
addZreo(num:number){
return num > 9?num.toString() : '0' + num.toString()
}
lastMonth(){
if(this.monthNow > 0){
this.monthNow -= 1
}else {
this.monthNow = 12
this.yearNow -= 1
}
this.getMonthContent()
}
nextMonth(){
if(this.monthNow < 12){
this.monthNow += 1
}else {
this.monthNow = 1
this.yearNow += 1
}
this.getMonthContent()
}
build() {
Column(){
Row({space:20}){
Image($r('app.media.last'))
.width(25)
.height(25)
.onClick(()=>{
this.lastMonth()
})
Text(this.yearNow.toString() + '-' + this.addZreo(this.monthNow))
.fontSize(15)
.fontColor(Color.Black)
.fontWeight(FontWeight.Bold)
Image($r('app.media.next'))
.width(25)
.height(25)
.onClick(()=>{
this.nextMonth()
})
}
.width('100%')
.height(40)
.justifyContent(FlexAlign.Center)
Column(){
Flex({direction:FlexDirection.Row,wrap:FlexWrap.NoWrap}){
ForEach(this.WEEKS,(str:string,index)=>{
Text(str)
.fontSize(14)
.fontColor(Color.Gray)
.textAlign(TextAlign.Center)
.width('50%')
.height(35)
})
}
Flex({direction:FlexDirection.Row,wrap:FlexWrap.Wrap}){
ForEach(this.MONTHDAY,(calendar:Calendar,index)=>{
Column({space:2}){
Text(calendar.day.toString())
.fontSize(16)
.fontColor(Color.Black)
.textAlign(TextAlign.Center)
.fontWeight(FontWeight.Bold)
Text(calendar.content)
.fontColor(Color.Gray)
.fontSize(10)
}
.justifyContent(FlexAlign.Center)
.padding({top:4})
.width('14.2%')
.height(60)
.alignItems(HorizontalAlign.Center)
.visibility(calendar.day == 0? Visibility.Hidden:Visibility.Visible)
.backgroundColor(Color.White)
})
}
}
}
.backgroundColor(Color.White)
.width('100%')
.padding({left:10,right:10})
}
}
export interface Calendar {
month: number; // 月
day: number; // 日
year:number; // 年
content: string; // 内容
}
在鸿蒙Next中开发一个月历组件的更多相关文章
- 如何从0开发一个Vue组件库并发布到npm
1.新建文件夹在终端打开执行 npm init -y 生成package.json如下,注意如果要发布到npm,name不能有下划线,大写字母等 { "name": "v ...
- 对jquery插件Jcrop开发一个裁剪组件
Jcrop是一款优秀的裁剪工具,它不仅可以裁剪图像,还可以裁剪canvas及任何的div元素,具体可参考: http://code.ciaoca.com/jquery/jcrop/ 基于Jcrop,开 ...
- 如何从0开发一个Atom组件
最近用Atom写博客比较多,然后发现一个很严重的问题..没有一个我想要的上传图片的方式,比如某乎上边就可以直接copy/paste文件,然后进行上传.然而在Atom上没有找到类似的插件,最接近的一个, ...
- 15分钟快速开发一个kissy组件(流程篇)
Step1: 安装kissy gallery组件工具 npm install yo grunt-cli -g npm install generator-kissy-gallery -g 请确保本地带 ...
- 从零开始开发一个vue组件打包并发布到npm (把vue组件打包成一个可以直接引用的js文件)
自己写的组件 有的也挺好的,为了方便以后用自己再用或者给别人用,把组件打包发布到npm是最好不过了,本次打包支持 支持正常的组件调用方式,也支持Vue.use, 也可以直接引用打包好的js文件, 配合 ...
- 在React中写一个Animation组件,为组件进入和离开加上动画/过度
问题 在单页面应用中,我们经常需要给路由的切换或者元素的挂载和卸载加上过渡效果,为这么一个小功能引入第三方框架,实在有点小纠结.不如自己封装. 思路 原理 以进入时opacity: 0 --> ...
- 在Visual Studio中开发一个C语言程序
→新建一个项目→选择"其他语言","Visual C++",并选择"win32控制台应用程序",并给控制台应用程序起名.→点击"下 ...
- 如何在react中实现一个倒计时组件
倒计时组件 import React, { Component } from 'react' import $ from 'jquery' import "../../css/spellTE ...
- 从0搭建Vue3组件库(四): 如何开发一个组件
本篇文章将介绍如何在组件库中开发一个组件,其中包括 如何本地实时调试组件 如何让组件库支持全局引入 如何在 setup 语法糖下给组件命名 如何开发一个组件 目录结构 在packages目录下新建co ...
- 架构师之路-在Dubbo中开发REST风格的远程调用
架构师之路:从无到有搭建中小型互联网公司后台服务架构与运维架构 http://www.roncoo.com/course/view/ae1dbb70496349d3a8899b6c68f7d10b 概 ...
随机推荐
- JAVA基础环境配置指南(简洁版)
1.安装JDK 官网下载后直接安装 配置环境变量: 添加 JAVA_HOME 变量名:JAVA_HOME 变量值:C:\Program Files (x86)\Java\jdk1.8.0_91 // ...
- 在 WPF 应用程序中缓存应用程序数据
参考学习链接:https://docs.microsoft.com/zh-cn/dotnet/framework/wpf/advanced/walkthrough-caching-applicatio ...
- [HDU5396] Expression 题解
每次合并两个数,做过石子合并的人都能看出来是区间 dp. 设状态 \(dp_{i,j}\) 表示区间 \([i,j]\) 中合并为一个数的所有情况之和. 那么我们就可以枚举断点 \(k\): \(b_ ...
- Java 实现 Excel(XLS/ XLSX)和 HTML 格式之间的转换
Excel 是一种电子表格格式,广泛用于数据处理和分析,而HTM则是一种用于创建网页的标记语言.虽然两者在用途上存在差异,但有时我们需要将数据从一种格式转换为另一种格式,以便更好地利用和展示数据.本文 ...
- Zookeeper、Hadoop、Hbase的启动顺序以及关闭顺序
启动顺序 Hadoop及hbase集群启动顺序 zookeepeer -> hadoop -> hbase 停止顺序 Hadoop及hbase集群关闭顺序 hbase -> hado ...
- php执行时间
要计算代码的bai执行时间,在PHP来讲是du十分简单的,首先,zhi你需要知道,PHP是一种dao顺序执行的脚本语言,所以,可以按照以下步骤来计算代码的执行时间: <?php function ...
- 【练习回顾】DS前三次作业
第一次作业 T2.基本计算器 使用了数组栈--数字栈和符号栈 T5.全排列输出(permutation) 使用了标准写法--字典序算法 void reverse(int left,int right) ...
- 启动本地node服务器报错: Access denied for user ‘root‘@‘localhost‘ (using password: YES)
背景:今天启动node服务时直接报错,顿时一激灵,之前(几个月前哈哈)明明好好的.主要问题就是在连接数据库上,我登上mysql瞅瞅有没有问题,当要输入密码时,emmm, 很好, 忘记root密码了,于 ...
- kubeadm init 或 join 失败 [kubelet-check] Initial timeout of 40s passed.
前言 kubeadm 初始化或 join 时,报错: [etcd] Creating static Pod manifest for local etcd in "/etc/kubernet ...
- MongoDB 复制集机制及原理
复制集的作用 MongoDB 复制集的主要意义在于实现服务高可用. 它的现实依赖于两个方面的功能: 数据写入时将数据迅速复制到另一个独立节点上 在接受写入的节点发生故障时自动选举出一个新的代替节点 在 ...