我們都知道,ios沒有日歷控件狡孔,要想在項(xiàng)目中加入日歷功能,就得自己開發(fā)蜂嗽。github上面也有很多大神封裝好的日歷控件苗膝,但是感覺用別人的改起來總是不太好,所以決定自己手動(dòng)開發(fā)一個(gè)日歷植旧。
開發(fā)思路:
日歷開發(fā)主要用的就是uicollectionview辱揭,對(duì)其進(jìn)行封裝處理离唐,還有使用NSCalendar的一些方法去計(jì)算數(shù)據(jù)。項(xiàng)目難點(diǎn)主要在于實(shí)現(xiàn)日歷可以左右無限滑動(dòng)问窃,這個(gè)可以用輪播方法進(jìn)行解決亥鬓。這邊博客主要是將開發(fā)思路,以及開發(fā)方法域庇,而github上的demo沒有進(jìn)行封裝嵌戈,因此你們?cè)趯W(xué)習(xí)日歷開發(fā)上才更容易看懂。這里我只寫一些主要的技術(shù)點(diǎn)听皿,具體實(shí)現(xiàn)大家可以下載我的demo進(jìn)行了解咕别。
技術(shù)點(diǎn)一:NSCalendar+JSCCalendar
我們先給NSCalendar增加一些方法,這里我用了分類思想写穴。為NSCalendar增加一分類JSCCalendar
技術(shù)點(diǎn)二.自定義UICollectionViewFlowLayout
為什么要自定義UICollectionViewFlowLayout呢?因?yàn)槲乙龅娜諝v是需要左右滑動(dòng)的雌贱,那么我們的collectview是肯定要設(shè)置為橫向滑動(dòng)嘍啊送,而如果設(shè)置橫向滑動(dòng),那么我們的item會(huì)怎樣展示呢欣孤,大家想一下馋没?想出問題沒?那如果我們?cè)谟胕tem的indexpath.item來作為數(shù)據(jù)展示的話降传,就會(huì)是下面這種效果了
因?yàn)檫@個(gè)是整體完成開發(fā)之后篷朵,又去改的UICollectionViewFlowLayout,因此沒有展示全婆排,但是可以看出CollectionView的item展示順序是從上往下從左往右開始排列的声旺,這樣會(huì)影響到我們對(duì)日歷數(shù)據(jù)源的讀取。
JSCCollectionViewFlowLayout.h文件
@interfaceJSCCollectionViewFlowLayout :UICollectionViewFlowLayout
//? ? 一頁顯示多少列
@property (nonatomic,assign) NSUInteger itemCountPerRow;
//? ? 一頁顯示多少行
@property (nonatomic,assign) NSUInteger rowCount;
JSCCollectionViewFlowLayout.m文件
以上自定義layou就可以讓CollectionView從左往右段只,從上往下進(jìn)行排列展示了腮猖。里面的方法看不懂沒關(guān)系,直接使用這個(gè)layout就可以赞枕。
技術(shù)點(diǎn)三:UICollectionViewCell展示
這里我說下兩個(gè)數(shù)據(jù)源澈缺,當(dāng)然具體獲得方法,在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;//三個(gè)月的日歷數(shù)據(jù)數(shù)組(例如:[ [1,2,3,...29,30,31],[1,2,3...28,29,30],[1,2,3...26,27,28] ])
? ? NSArray * _threedateArray;//三個(gè)月的今天數(shù)據(jù)數(shù)組(例如:2018-03-18姐赡,2018-04-18,2018-05-18)
技術(shù)點(diǎn)四:輪播實(shí)現(xiàn)無限左右滑動(dòng)
設(shè)置ContentOffset
#pragma mark - 設(shè)置collectionview的ContentOffset
- (void)repositionViews{
? ? [_collectionView setContentOffset:CGPointMake(self.view.frame.size.width*round(NUMBER_PAGES_LOADED/2), 0)];
}
這里解釋下柠掂,為何日歷能實(shí)現(xiàn)左右滑動(dòng)项滑,其實(shí)就是一個(gè)輪播效果,我們?cè)趯?duì)collectionview進(jìn)行了3個(gè)section的創(chuàng)建陪踩,同時(shí)將ContentOffset設(shè)置到self.view.frame.size.width杖们,我們的手機(jī)屏幕和collectionview應(yīng)該是這樣的:
那么悉抵,每次當(dāng)我們往右邊滑動(dòng)屏幕,這時(shí)候section0會(huì)慢慢出現(xiàn)在手機(jī)屏幕里摘完,一旦section0完全移動(dòng)到屏幕中間姥饰。
1.這時(shí)候我們馬上把當(dāng)前時(shí)間改為seciton0的時(shí)間3月,然后重新獲取到2月份孝治,3月份和4月份的數(shù)據(jù)放在數(shù)據(jù)源中
2.由于我們的滑動(dòng)列粪,contentofset的x已經(jīng)為0了,這時(shí)候在設(shè)置為self.view.frame.size.width谈飒,讓它回到屏幕中間
3.計(jì)算3月份的日歷是顯示幾行岂座,重新計(jì)算CollectionView的frame,計(jì)算萬不要用layoutIfNeeded方法杭措,因?yàn)橄乱徊轿覀兯⑿翪ollectionView數(shù)據(jù)源费什,frame自然會(huì)改變。
4.刷新數(shù)據(jù)手素。當(dāng)我們手動(dòng)設(shè)置contentofset回到中間之后鸳址,應(yīng)該會(huì)展示4月份的數(shù)據(jù)對(duì)吧,這時(shí)候我們r(jià)eloadData泉懦,那么CollectionView的數(shù)據(jù)源變了稿黍,就會(huì)顯示3月份的數(shù)據(jù)了。給用戶的效果就是無限滑動(dòng)了崩哩。
注意:reloadData的時(shí)候要在? performWithoutAnimation?里面巡球,因?yàn)椴贿@樣的話,當(dāng)我們的cell有過顏色渲染的時(shí)候邓嘹,刷新會(huì)出現(xiàn)閃爍
這里我用了很多圖片酣栈,是因?yàn)椋野l(fā)現(xiàn)引用代碼的時(shí)候汹押,簡書會(huì)給我自動(dòng)刪除一些空格 導(dǎo)致我的方法調(diào)用等等出現(xiàn)問題钉嘹,所以如果有知道如果解決方法的小伙伴,麻煩給我說一下鲸阻。