我们都知道,ios没有日历控件,要想在项目中加入日历功能,就得自己开发。github上面也有很多大神封装好的日历控件,但是感觉用别人的改起来总是不太好,所以决定自己手动开发一个日历。
开发思路:
日历开发主要用的就是uicollectionview,对其进行封装处理,还有使用NSCalendar的一些方法去计算数据。项目难点主要在于实现日历可以左右无限滑动,这个可以用轮播方法进行解决。这边博客主要是将开发思路,以及开发方法,而github上的demo没有进行封装,因此你们在学习日历开发上才更容易看懂。这里我只写一些主要的技术点,具体实现大家可以下载我的demo进行了解。
技术点一:NSCalendar+JSCCalendar
我们先给NSCalendar增加一些方法,这里我用了分类思想。为NSCalendar增加一分类JSCCalendar
技术点二.自定义UICollectionViewFlowLayout
为什么要自定义UICollectionViewFlowLayout呢?因为我要做的日历是需要左右滑动的,那么我们的collectview是肯定要设置为横向滑动喽,而如果设置横向滑动,那么我们的item会怎样展示呢,大家想一下?想出问题没?那如果我们在用item的indexpath.item来作为数据展示的话,就会是下面这种效果了
因为这个是整体完成开发之后,又去改的UICollectionViewFlowLayout,因此没有展示全,但是可以看出CollectionView的item展示顺序是从上往下从左往右开始排列的,这样会影响到我们对日历数据源的读取。
JSCCollectionViewFlowLayout.h文件
@interfaceJSCCollectionViewFlowLayout :UICollectionViewFlowLayout
// 一页显示多少列
@property (nonatomic,assign) NSUInteger itemCountPerRow;
// 一页显示多少行
@property (nonatomic,assign) NSUInteger rowCount;
JSCCollectionViewFlowLayout.m文件
以上自定义layou就可以让CollectionView从左往右,从上往下进行排列展示了。里面的方法看不懂没关系,直接使用这个layout就可以。
技术点三:UICollectionViewCell展示
这里我说下两个数据源,当然具体获得方法,在NSCalendar的分类中都可以找到。
_daysInMonth = [self.calendar threedateArray:_currentDate];
NSDate*lastdate = [self.calendar lastMonth:_currentDate];
NSDate*nextdate = [self.calendar nextMonth:_currentDate];
_threedateArray= [NSArray arrayWithObjects:lastdate,_currentDate, nextdate,nil];
NSArray* _daysInMonth;//三个月的日历数据数组(例如:[ [1,2,3,...29,30,31],[1,2,3...28,29,30],[1,2,3...26,27,28] ])
NSArray * _threedateArray;//三个月的今天数据数组(例如:2018-03-18,2018-04-18,2018-05-18)
技术点四:轮播实现无限左右滑动
设置ContentOffset
#pragma mark - 设置collectionview的ContentOffset
- (void)repositionViews{
[_collectionView setContentOffset:CGPointMake(self.view.frame.size.width*round(NUMBER_PAGES_LOADED/2), 0)];
}
这里解释下,为何日历能实现左右滑动,其实就是一个轮播效果,我们在对collectionview进行了3个section的创建,同时将ContentOffset设置到self.view.frame.size.width,我们的手机屏幕和collectionview应该是这样的:
那么,每次当我们往右边滑动屏幕,这时候section0会慢慢出现在手机屏幕里,一旦section0完全移动到屏幕中间。
1.这时候我们马上把当前时间改为seciton0的时间3月,然后重新获取到2月份,3月份和4月份的数据放在数据源中
2.由于我们的滑动,contentofset的x已经为0了,这时候在设置为self.view.frame.size.width,让它回到屏幕中间
3.计算3月份的日历是显示几行,重新计算CollectionView的frame,计算万不要用layoutIfNeeded方法,因为下一步我们刷新CollectionView数据源,frame自然会改变。
4.刷新数据。当我们手动设置contentofset回到中间之后,应该会展示4月份的数据对吧,这时候我们reloadData,那么CollectionView的数据源变了,就会显示3月份的数据了。给用户的效果就是无限滑动了。
注意:reloadData的时候要在 performWithoutAnimation 里面,因为不这样的话,当我们的cell有过颜色渲染的时候,刷新会出现闪烁
这里我用了很多图片,是因为,我发现引用代码的时候,简书会给我自动删除一些空格 导致我的方法调用等等出现问题,所以如果有知道如果解决方法的小伙伴,麻烦给我说一下。
网友评论