授權轉載,作者:codingZero(簡書)
不啰嗦,直接上思路。
時間選擇就不說了,界面固定的,說說日期選擇。
日期選擇其實就是一個collectionView,collectionView的item數量,取決與日歷的開始日期與結束日期。
假設開始日期為1970-01-01,結束日期為當前日期
那item的數量 = 當前日期與開始日期相差的天數 + 1 + 4(1970-01-01是星期四),為什麼要+1,自己領悟,如圖
接下來就是cell的賦值,其實這個也是非常簡單的,代碼如下,開始日期是星期幾就從第幾個cell開始賦值(星期日是第0個)。開始日期+indexPath.item - 開始日期的星期,就能得到該cell對應的日期,然後將日期中的多少號顯示在cell上就行了,如果是1號,就把月份也顯示出來
if (indexPath.item >= _firstWeekday) { item.date = [DateTool date:self.startDate addDays:indexPath.item - _firstWeekday]; } else { item.date = nil; }
cell中的代碼
- (void)setDate:(NSDate *)date { _date = date; if (!date) { _monthLabel.text = @""; _dayLabel.text = @""; return; } NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:date]; if (components.day == 1 || [[NSCalendar currentCalendar] isDateInToday:date]) { _monthLabel.text = [NSString stringWithFormat:@"%@", self.months[components.month - 1]]; } else { _monthLabel.text = @""; } _dayLabel.text = [NSString stringWithFormat:@"%ld", components.day]; }
上面說的這些都挺簡單的,接下來說說下面這個功能的實現,如圖
滾動collectionView的時候,上面會出現對應的年份與月份,筆者的做法是,collectionView上面疊加了一個tableview,滾動collectionView的同時,同步滾動tableview。
這裡的難點就在於同步,如何保證tableview上的日期與collectionView上的日期正好對應上,進一步說,難點在於tableviewCell高度的計算,把tableviewCell的高度計算對了,剩下的就簡單了
Cell高度的計算
其實在做之前,筆者也覺得這個高度的計算一定很難,但是有了思路之後,發覺還是非常簡單的,只要你不是數學白癡,就能看懂
以下面的圖為例:
我們先看第一個cell,這個cell的高度為collectionView中3個item的高度。
這個3是怎麼算出來的?很簡單,開始日期我們知道,那我們就可以取出開始月份的最後一天,這裡是1974-11-30,然後我們計算出這個日期與開始日期相差的天數 + 1 + 6(開始日期是周六),然後(天數 + 6)/ 7,取整就可以得到3了,不要問我為什麼+6。
第二個cell高度的計算也類似,不過這需要依賴第一個cell的高度,我們在開始日期的基礎上+1個月,取出這個月最後一天的日期並計算與開始日期相差的天數,然後算出總高度,再用這個高度減去上一個cell的高度,就可以得到第二個cell的高度了。
後面的以此類推,最後一個略有不同,最後一個月不能取最後一天的日期,而是要取結束日期
這樣計算出來的cell的總高度最終與collectionView的contentSize.height是一樣的,所以要保證同步,只需要在滾動collectionView的時候,設置tableview的垂直偏移量與collectionView的一致就行了
結束語
表達的可能不是很清楚,有興趣研究的可以到筆者的Github下載!地址:https://github.com/codingZero/XRCalendarView。