項目需要,前一陣子重構了下iPad工程,添加了一個滾動無縫日曆。 當時沒有頭緒,網上找了一個源碼改吧改吧就上線了(參考鏈接),這個功能很多而且流暢性也特別好,推薦不會寫的可以參考下。 這幾天,活不太忙就把日曆控制項裁剪了下,做個最簡單的滾動無縫日曆。效果如下圖: 日曆可以左右滾動,點擊某個日期後會變色 ...
項目需要,前一陣子重構了下iPad工程,添加了一個滾動無縫日曆。
當時沒有頭緒,網上找了一個源碼改吧改吧就上線了(參考鏈接),這個功能很多而且流暢性也特別好,推薦不會寫的可以參考下。
這幾天,活不太忙就把日曆控制項裁剪了下,做個最簡單的滾動無縫日曆。效果如下圖:
日曆可以左右滾動,點擊某個日期後會變色,並且有回調。橘色的是標記日期,藍色的是選擇日期,藍邊的是當前日期,可以根據需要自行更改。
這個日曆控制項有兩個比較複雜的地方:
- UICollectionView預設情況下,橫滾cell豎排豎滾cell橫排,所以我們先要修改下cell的位置,自定義FlowLayout繼承於UICollectionViewFlowLayout,重寫它的prepareLayout方法。
#import "EXCalendarCollectionViewFlowLayout.h" @interface EXCalendarCollectionViewFlowLayout () @property (nonatomic, strong) NSMutableArray *allAttributes; @end @implementation EXCalendarCollectionViewFlowLayout - (void)prepareLayout { [super prepareLayout]; self.allAttributes = [NSMutableArray array]; NSInteger sections = [self.collectionView numberOfSections]; for (int i = 0; i < sections; i++) { // setup one section attributes. NSMutableArray *tmpArray = [NSMutableArray array]; NSInteger count = [self.collectionView numberOfItemsInSection:i]; for (NSInteger j = 0; j < count; j++) { NSIndexPath *indexPath = [NSIndexPath indexPathForItem:j inSection:i]; UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath]; [tmpArray addObject:attributes]; } [self.allAttributes addObject:tmpArray]; } } - (CGSize)collectionViewContentSize { return [super collectionViewContentSize]; } - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { NSInteger item = indexPath.item; NSInteger x; NSInteger y; // 根據item的序號計算出item的行列位置 [self targetPositionWithItem:item resultX:&x resultY:&y]; // 根據已得出的item的行列位置,將item放入indexPath中對應的位置。 NSInteger item2 = [self orignItemAtX:x y:y]; NSIndexPath *theNewIndexPath = [NSIndexPath indexPathForItem:item2 inSection:indexPath.section]; UICollectionViewLayoutAttributes *theNewAttr = [super layoutAttributesForItemAtIndexPath:theNewIndexPath]; theNewAttr.indexPath = indexPath; return theNewAttr; } - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect { NSArray *attributes = [super layoutAttributesForElementsInRect:rect]; NSMutableArray *tmp = [NSMutableArray array]; for (UICollectionViewLayoutAttributes *attr in attributes) { for (NSMutableArray *attributes in self.allAttributes) { for (UICollectionViewLayoutAttributes *attr2 in attributes) { if (attr.indexPath.item == attr2.indexPath.item) { [tmp addObject:attr2]; break; } } } } return tmp; } // 根據item計算目標item的位置。 - (void)targetPositionWithItem:(NSInteger)item resultX:(NSInteger *)x resultY:(NSInteger *)y { // NSInteger page = item / (self.itemCountPerRow * self.rowCountPerPage); NSInteger theX = item % self.itemCountPerRow; NSInteger theY = item / self.itemCountPerRow; if (x != NULL) { *x = theX; } if (y != NULL) { *y = theY; } } - (NSInteger)orignItemAtX:(NSInteger)x y:(NSInteger)y { NSInteger item = x * self.rowCountPerPage + y; return item; } @end
View Code - 當你在當前月份點擊了一個日期,滑到其他月份,然後要對剛纔選擇的月份的效果進行更改時,比較麻煩。剛開始我在didSelectItemAtIndexPath委托方法中用cellForItemAtIndexPath進行獲取時,不可見的cell獲取不到返回的是空,然後在如何獲取不可見的cell問題上糾結了兩天,最終換了個解決方案,在cellForItemAtIndexPath中進行了判斷,解決了這個問題,當然點擊後直接有響應跳轉的話,剛纔這個功能就很雞肋了。具體看代碼吧。
源碼地址:https://github.com/zhanghua0926/EXCalendar