用NSCalendar和UICollectionView自定义日历,并实现签到显示

news/2024/7/8 5:24:33

前一段时间因为工作需要实现了一个可以签到的日历,来记录一下实现的思路
效果如图:
 
这里的基本需求是:
1,显示用户某个月的签到情况,已经签到的日子打个圈,没有签到且在某个时间范围内的可以签到,其他的只能看。
2,服务器只会返回这个月用户签到日子的时间戳数组和可以签到的时间范围,剩下的日子就是没有签到的。
3,显示跟普通的日历一样即可,上面是“一二三四五六日”,下面是对应的日期。
4,可以切换到当前日期之前的月份。
 
根据需求,基本思路是:
用一个pageViewController作为基本控制器,控制显示某月签到情况的viewController;
(为什么用pageViewController呢?因为需求要求可以切换月份,用pageViewController方便复用,而且每个月可能都需要请求服务器数据,将网络请求写到viewController当中更好控制整个生命周期)
每个viewController是一个月的情况,上面放一个自定义的calendarView,
用UICollectionView实现CalendarView,每个cell显示一天日期,
定义几个状态分别表示可签到,不可签到,已签到等状态,然后配置好cell的状态就行了。
 
界面的设计大概就是这个样子,难点是日历的逻辑和数据配置问题
 
首先,要根据服务器返回的时间戳确定今天的日期及当月的DateComponents(防止用户修改系统时间来作弊,用NSDateComponents表示某个月方便比较);
然后,根据当月的dateComponents显示日历,
这里需要注意的是,要想办法获取到当月有多少天和当月的第一天是星期几!!!
       获取当月第一天的dateComponents:
    NSDateComponents *firstDayComponents = [[NSDateComponents alloc] init];
    firstDayComponents.year = monthComponents.year;
    firstDayComponents.month = monthComponents.month;
    firstDayComponents.day = 1;
 
然后就可以用NSCalendar的api提供的方法
    NSDate *firstDay = [self.calendar dateFromComponents:firstDayComponents];
    NSDateComponents *dateComponents = [self.calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitWeekday fromDate:firstDay];
    NSRange range = [self.calendar rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:firstDay];//指定日期的day在month中的位置
所以range的length就是当月有多少天,dateComponents.weekday就是当月第一天是周几。
这里又需要注意,NSCalendar的firstWeekday和minimumDaysInFirstWeek属性:
- (NSCalendar *)calendar {
    if (!_calendar) {
        _calendar = [NSCalendar currentCalendar];
        _calendar.firstWeekday = 2;//1是周日,2是周一,以此类推
        _calendar.minimumDaysInFirstWeek = 1;//表示一个月的最初一周如果少于这个值,则算为上个月的最后一周,大约等于则算本月第一周,用1就好
    }
    return _calendar;
}
 
有了这些就可以算出当月第一天之前有多少空白cell:
    self.frontBlankCount  = dateComponents.weekday - self.calendar.firstWeekday;
    if (self.frontBlankCount  < 0) {
        //这里,因为weekday周日是1,所以判断下
        self.frontBlankCount  += 7;
    }
然后算出当月最后有多少空白:
    for (int i = 0; i < self.frontBlankCount; i++) {
        //这里是让每个月最开始的地方按需求空白
        [self.dataArray addObject:@""];
    }
    for (int i = 0; i < range.length; i++) {
        NSString *text = [NSString stringWithFormat:@"%@", @(i + 1)];
        [self.dataArray addObject:text];
    }
   
    NSInteger weeks = 0; //每个月有几周
    NSInteger aaa = self.dataArray.count / 7;
    NSInteger bbb = self.dataArray.count % 7;
    if (bbb == 0) {
        weeks = aaa;
    } else {
        weeks = aaa + 1;
    }
    self.backBlankCount = weeks * 7 - self.dataArray.count;
到这里日历就可以完整的显示出来了。
 
剩下的就是匹配签到数据:
只需要一个for循环,判断日历日期是否在服务器返回的签到日期之中就可以了;
如果需要判断是否可以签到,加入一个时间戳大小的判断就行。
最后再reloadData就可以了~~~
 
demo在github上: https://github.com/Phelthas/Demo_Calendar

转载于:https://www.cnblogs.com/Phelthas/p/5313485.html


http://www.niftyadmin.cn/n/2266050.html

相关文章

深入Java虚拟机(3)——安全

转载: 深入Java虚拟机&#xff08;3&#xff09;——安全 因为网络允许多台计算机共享数据和分布式处理&#xff0c;所以它提供了一条入侵计算机系统的潜在途径&#xff0c;使得其他人可以窃取信息&#xff0c;改变或破坏信息&#xff0c;盗取计算机资源等等。为了解决由网络引…

Markdown写作

word:富文本编辑器 缺点&#xff1a;二次处理不方便&#xff1b;富文本格式在版本管理工具里不方便 元素Markdown语法标题&#xff08;Heading&#xff09; # H1 ## H2 ### H3 粗体&#xff08;Bold&#xff09;**blod text**斜体&#xff08;Italic&#xff09;*italicized …

HTML模板含义

<!DOCTYPE html> //HTML版本是HTML5 <html lang"en"> //languageEnglish&#xff0c;语言是英文&#xff0c;如果为中文页面&#xff0c;lang"zh" <head> //头标签<meta charset"UTF-8"> //字符编码格式<meta…

HTML5结构标签

1.页眉标签header 用于定义网页文档或节的页眉&#xff0c;通常为网站名称。 2.导航标签nav 用于定义网页文档的导航菜单&#xff0c;可通过超链接跳转至其他页面。nav为navigation简写。 3.节标签section 用于定义独立的专题区域&#xff0c;里面可包含一片货多篇文章。 …

CSS清除浮动的用途及方法

应用场景一 未添加浮动&#xff1a; 添加浮动后&#xff08;想让3位于1&#xff0c;2下面&#xff09;&#xff1a; *{margin:0;padding:0; } .container{border:1px solid black; } .first{background:yellow;width:100px;height:100px;float:right; } .second{background:gr…

CSS3转换、过渡、动画

一、转换&#xff08;transform&#xff09; 移动、旋转、缩放、倾斜元素 CSS 2D转换方法&#xff1a; CSS 3D转换 二、CSS过渡 1.要添加效果的 CSS 属性 2.效果的持续时间 transition-timing-function 属性指定过渡效果的速度曲线 取值&#xff1a; ease - 规定过渡效果…

HDU 3416 Marriage Match IV dij+dinic

题意&#xff1a;给你n个点,m条边的图&#xff08;有向图&#xff0c;记住一定是有向图&#xff09;&#xff0c;给定起点和终点&#xff0c;问你从起点到终点有几条不同的最短路 分析&#xff1a;不同的最短路&#xff0c;即一条边也不能相同&#xff0c;然后刚开始我的想法是…