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

这样的组件大家在工作中应该经常会遇到,而鸿蒙又没有提供一个这样的系统组件,今天我们就来看看怎么实现它。
标题部分比较简单,由两个箭头图片和一个文本组件构成,不再赘述。

下面的‘星期’部分有很多方式去实现,这里我选择使用弹性布局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中开发一个月历组件的更多相关文章

  1. 如何从0开发一个Vue组件库并发布到npm

    1.新建文件夹在终端打开执行 npm init -y 生成package.json如下,注意如果要发布到npm,name不能有下划线,大写字母等 { "name": "v ...

  2. 对jquery插件Jcrop开发一个裁剪组件

    Jcrop是一款优秀的裁剪工具,它不仅可以裁剪图像,还可以裁剪canvas及任何的div元素,具体可参考: http://code.ciaoca.com/jquery/jcrop/ 基于Jcrop,开 ...

  3. 如何从0开发一个Atom组件

    最近用Atom写博客比较多,然后发现一个很严重的问题..没有一个我想要的上传图片的方式,比如某乎上边就可以直接copy/paste文件,然后进行上传.然而在Atom上没有找到类似的插件,最接近的一个, ...

  4. 15分钟快速开发一个kissy组件(流程篇)

    Step1: 安装kissy gallery组件工具 npm install yo grunt-cli -g npm install generator-kissy-gallery -g 请确保本地带 ...

  5. 从零开始开发一个vue组件打包并发布到npm (把vue组件打包成一个可以直接引用的js文件)

    自己写的组件 有的也挺好的,为了方便以后用自己再用或者给别人用,把组件打包发布到npm是最好不过了,本次打包支持 支持正常的组件调用方式,也支持Vue.use, 也可以直接引用打包好的js文件, 配合 ...

  6. 在React中写一个Animation组件,为组件进入和离开加上动画/过度

    问题 在单页面应用中,我们经常需要给路由的切换或者元素的挂载和卸载加上过渡效果,为这么一个小功能引入第三方框架,实在有点小纠结.不如自己封装. 思路 原理 以进入时opacity: 0 --> ...

  7. 在Visual Studio中开发一个C语言程序

    →新建一个项目→选择"其他语言","Visual C++",并选择"win32控制台应用程序",并给控制台应用程序起名.→点击"下 ...

  8. 如何在react中实现一个倒计时组件

    倒计时组件 import React, { Component } from 'react' import $ from 'jquery' import "../../css/spellTE ...

  9. 从0搭建Vue3组件库(四): 如何开发一个组件

    本篇文章将介绍如何在组件库中开发一个组件,其中包括 如何本地实时调试组件 如何让组件库支持全局引入 如何在 setup 语法糖下给组件命名 如何开发一个组件 目录结构 在packages目录下新建co ...

  10. 架构师之路-在Dubbo中开发REST风格的远程调用

    架构师之路:从无到有搭建中小型互联网公司后台服务架构与运维架构 http://www.roncoo.com/course/view/ae1dbb70496349d3a8899b6c68f7d10b 概 ...

随机推荐

  1. DotNet跨平台 - docker+nginx+ssl 负载均衡

    环境:CentOS7 服务器需要安装:docker.nginx.OpenSSL 一.部署方案 在linux服务器上,我们的Web站点程序采用docker容器部署,为了演示负载均衡,我们在同一台linu ...

  2. 历时两天半由浅入深总结了20道Vue高频面试题

    作为一个程序员如果你想要找到你心仪的工作,不可避免的就会问到很多八股文,虽然有的和工作没有半毛钱关系,但是你如果想要通过面试还必须得会.所以我最近开始总结一些面试题,一是为了加强自己的理解能够找到一份 ...

  3. autMan奥特曼机器人-代理池配置教程

    一.优势: 全可视化 稳如老牛(从2.8.6开始) 隧道代理和接口获取,使用灵活 代理池运行状态指令可查:代理池 二.启用代理池并设置服务端口 代理池的启用与关闭,均为重启autMan生效 设置隧道代 ...

  4. NebulaGraph Desktop 使用初体验

    前言 前两天 NebulaGraph 官方宣布了全新的开源 Desktop,旨在通过一体化方案解决图数据库部署复杂.工具碎片化.学习成本高等的痛点问题,我也是跃跃欲试.前期在初识 NebulaGrap ...

  5. 在Linux系统下启动eclipse时遇到Eclipse 无法正常启动

    Eclipse: 无法打开显示: 出现此问题原因: 这通常表示 Eclipse 试图在没有合适显示环境的情况下启动,可能是在没有图形界面的环境(例如远程服务器或没有正确配置的 X11 转发)中运行. ...

  6. C/C++显示类型转换的位拓展方式

    最近用verilator写模块的tb,在这里卡了好久(测半天都是C++写的问题) 要点 变量从小位宽到大位宽显示类型转换(explicit cast)时的位拓展方式,取决于转换前变量的符号性. 倘若转 ...

  7. composer 2 升级操作

    update composer composer self-update // or sudo composer self-update 回滚到版本1 composer self-update --r ...

  8. 浅说树形dp

    @ 目录 前言 树形dp的转移方式 树形dp的使用的场景 小结 初步感知--简单的树形dp 例题1 例题2 深入分析--树形dp的经典模型 最大独立集 最小点覆盖 最小支配集 树上直径 前言 因为树的 ...

  9. Kubernetes:根据进程 Pid 获取 Pod 名称

    前言 在管理 Kubernetes 集群的过程中,我们经常会遇到这样一种情况:在某台节点上发现某个进程资源占用量很高,却又不知道是哪个容器里的进程.有没有办法可以根据进程 PID 快速找到 Pod 名 ...

  10. Linux系统挂载未分配硬盘空间

    先查看未挂载之前的磁盘使用情况 发现磁盘使用率已经达到了96%,迫切需要扩容 查看分区情况fdisk –l 首先确保有可分配的磁盘空间 发现/dev/vda下有400多个G 的空间 所以将/dev/v ...