UICollectionView

引用自:http://www.lxweimin.com/p/c59a5c92f859

一、UICollectionVIew基礎

第一步:創建布局對象:

如果使用系統的布局類,我們通常是使用其UICollectionViewFlowLayout子類,通過這個子類來創建我們的布局對象。實例:UICollectionVIewFlowLayout *flowLayout = [UICollectionVIewFlowLayout new];

通過這個實例化的對象提供了一些基本的屬性,用于幫助我們控制布局的方式,當然這個類也有其自身的協議,通過簽署協議可以實現協議中的一些方法,這些方法可以幫助我們實現更加完善的布局。協議名字叫做:“UICollectionVIewDelegateFlowLayout”,這個協議也是實現基本CollectionVIew的三個協議中必須用到的,其他另外兩個協議分別是:UICollectionViewDataSource(數據源)、UICollectionViewDelegate。

下面簡單介紹一些關于這個類對象用于實現布局的屬性有哪些:

@property(nonatomic)CGFloatminimumLineSpacing;// 這個用于指定每個Item的行間距,默認間距是10.

@property(nonatomic)CGFloatminimumInteritemSpacing;//用于指定每個單元的列間距。

@property(nonatomic)CGSizeitemSize;//指定每個cell的size.

@property(nonatomic)CGSizeestimatedItemSizeNS_AVAILABLE_IOS(8_0);//defaults to CGSizeZero - setting a non-zero size enables cells that self-size via -preferredLayoutAttributesFittingAttributes:

@property(nonatomic)UICollectionViewScrollDirectionscrollDirection;// default is UICollectionViewScrollDirectionVertical

@property(nonatomic)CGSizeheaderReferenceSize;

@property(nonatomic)CGSizefooterReferenceSize;//頭部增添視圖的size

@property(nonatomic)UIEdgeInsetssectionInset;//設置分區的內邊距距離上左下右的距離,所以這個參數有四個參數。

// Set these properties to YES to get headers that pin to the top of the screen and footers that pin to the bottom while scrolling (similar to UITableView).

@property(nonatomic)BOOLsectionHeadersPinToVisibleBoundsNS_AVAILABLE_IOS(9_0);

@property(nonatomic)BOOLsectionFootersPinToVisibleBoundsNS_AVAILABLE_IOS(9_0);c//用于控制是否在當前窗口顯示下一個分區的尾增添

第二步:通過布局對象創建UICollectionView,并設置相關屬性,重點是給代理屬性給定對象。

初始化UICollectionVIew的方法:

Frame:指定UICollectionView的Frame

collectionViewLayout:指定UICollectView的布局對象。

- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout*)layoutNS_DESIGNATED_INITIALIZER;

第三步:設置好各個重用標識

這里就不多說了,在代碼的全局位置指定三個全局字符常量。

第四步:使用重用標識注冊相關的重用池。

cell的重用池的注冊方法:

Class:指定用哪個類作為cell,所以我們可以通過新建繼承自UICollectionViewLayout的類來自定義cell.

- (void)registerClass:(nullableClass)cellClass forCellWithReuseIdentifier:(NSString*)identifier;

補充視圖重用池的注冊方法:

forSupplementaryViewOfKind:指定補充視圖的類型

withReuseIdentifier:指定一個重用標識符

- (void)registerClass:(nullableClass)viewClass forSupplementaryViewOfKind:(NSString*)elementKind withReuseIdentifier:(NSString*)identifier;

第五步:實現UICollectionViewDataSource的幾個代理方法(這里只提幾個常用的)

#pragma?mark?----?UICollectionViewDataSource

// ?指定在一個CollectionView上分區的數量。

-?(NSInteger)numberOfSectionsInCollectionView:(UICollectionView?*)collectionView

{

return?1;

}

// 指定在每個分區上Item的數量。

-?(NSInteger)collectionView:(UICollectionView?*)collectionView?numberOfItemsInSection:(NSInteger)section

{

return?_section0Array.count;

}

// 從重用池中取出UICollectionVIew的celle來給每個Item賦值。

-?(UICollectionViewCell?*)collectionView:(UICollectionView?*)collectionView?cellForItemAtIndexPath:(NSIndexPath?*)indexPath

{

UICollectionViewCell?*cell?=?[_collectionView?dequeueReusableCellWithReuseIdentifier:cellId?forIndexPath:indexPath];

cell.backgroundColor?=?[UIColor?purpleColor];

return?cell;

}

//?和UITableView類似,UICollectionView也可設置段頭段尾

這個方法中的參數分別是:

collectionView:這個就不解釋了,每個協議中必須傳入的跟類。

viewForSupplementaryElementOfKind:根據傳入的Kind值來判斷到底添加的是那種類型的視圖。

atIndexPath:這個參數通過傳值來確定到底給那個分區補充視圖。

-?(UICollectionReusableView?*)collectionView:(UICollectionView?*)collectionView?viewForSupplementaryElementOfKind:(NSString?*)kind?atIndexPath:(NSIndexPath?*)indexPath

{

if([kind?isEqualToString:UICollectionElementKindSectionHeader])

{

UICollectionReusableView?*headerView?=?[_collectionView?dequeueReusableSupplementaryViewOfKind:kind?withReuseIdentifier:headerId?forIndexPath:indexPath];

if(headerView?==?nil)

{

headerView?=?[[UICollectionReusableView?alloc]?init];

}

headerView.backgroundColor?=?[UIColor?grayColor];

return?headerView;

}

else?if([kind?isEqualToString:UICollectionElementKindSectionFooter])

{

UICollectionReusableView?*footerView?=?[_collectionView?dequeueReusableSupplementaryViewOfKind:kind?withReuseIdentifier:footerId?forIndexPath:indexPath];

if(footerView?==?nil)

{

footerView?=?[[UICollectionReusableView?alloc]?init];

}

footerView.backgroundColor?=?[UIColor?lightGrayColor];

return?footerView;

}

return?nil;

}

// 暫時理解為:能夠移動的Item,有待驗證。

-?(BOOL)collectionView:(UICollectionView?*)collectionView?canMoveItemAtIndexPath:(NSIndexPath?*)indexPath

{

return?YES;

}

// ?暫時理解為:給能夠移動的Item指定移動路徑,有待驗證。

moveItemAtIndexPath:能夠一定的Item路徑。

toIndexPath:移動到的目標路徑。

-?(void)collectionView:(UICollectionView?*)collectionView?moveItemAtIndexPath:(NSIndexPath?*)sourceIndexPath?toIndexPath:(NSIndexPath*)destinationIndexPath

{

}

第六步:實現UICollectionViewDelegateFlowLayout協議方法(這里的很多方法用屬性的點語法同樣可以實現,建議使用點語法。)

-?(CGSize)collectionView:(UICollectionView?*)collectionView?layout:(UICollectionViewLayout*)collectionViewLayout?sizeForItemAtIndexPath:(NSIndexPath?*)indexPath

{

return?(CGSize){cellWidth,cellWidth};

}

-?(UIEdgeInsets)collectionView:(UICollectionView?*)collectionView?layout:(UICollectionViewLayout*)collectionViewLayout?insetForSectionAtIndex:(NSInteger)section

{

return?UIEdgeInsetsMake(5,?5,?5,?5);

}

-?(CGFloat)collectionView:(UICollectionView?*)collectionView?layout:(UICollectionViewLayout*)collectionViewLayout?minimumLineSpacingForSectionAtIndex:(NSInteger)section

{

return?5.f;

}

-?(CGFloat)collectionView:(UICollectionView?*)collectionView?layout:(UICollectionViewLayout*)collectionViewLayout?minimumInteritemSpacingForSectionAtIndex:(NSInteger)section

{

return?5.f;

}

-?(CGSize)collectionView:(UICollectionView?*)collectionView?layout:(UICollectionViewLayout*)collectionViewLayout?referenceSizeForHeaderInSection:(NSInteger)section

{

return?(CGSize){ScreenWidth,44};

}

-?(CGSize)collectionView:(UICollectionView?*)collectionView?layout:(UICollectionViewLayout*)collectionViewLayout?referenceSizeForFooterInSection:(NSInteger)section

{

return?(CGSize){ScreenWidth,22};

}

第七步:實現UICollectionViewDelegate方法

// 指定那些Item需要高亮顯示

-?(BOOL)collectionView:(UICollectionView?*)collectionView?shouldHighlightItemAtIndexPath:(NSIndexPath?*)indexPath

{

return?YES;

}

//?點擊高亮

-?(void)collectionView:(UICollectionView?*)collectionView?didHighlightItemAtIndexPath:(NSIndexPath?*)indexPath

{

UICollectionViewCell?*cell?=?[collectionView?cellForItemAtIndexPath:indexPath];

cell.backgroundColor?=?[UIColor?greenColor];

}

//?選中某item

-?(void)collectionView:(UICollectionView?*)collectionView?didSelectItemAtIndexPath:(NSIndexPath?*)indexPath

{

}

//?長按某item,彈出copy和paste的菜單

-?(BOOL)collectionView:(UICollectionView?*)collectionView?shouldShowMenuForItemAtIndexPath:(NSIndexPath?*)indexPath

{

return?YES;

}

//?使copy和paste有效

-?(BOOL)collectionView:(UICollectionView?*)collectionView?canPerformAction:(SEL)action?forItemAtIndexPath:(NSIndexPath?*)indexPath?withSender:(nullable?id)sender

{

if?([NSStringFromSelector(action)?isEqualToString:@"copy:"]?||?[NSStringFromSelector(action)?isEqualToString:@"paste:"])

{

return?YES;

}

return?NO;

}

//

-?(void)collectionView:(UICollectionView?*)collectionView?performAction:(SEL)action?forItemAtIndexPath:(NSIndexPath?*)indexPath?withSender:(nullable?id)sender

{

if([NSStringFromSelector(action)?isEqualToString:@"copy:"])

{

//? ? ? ? NSLog(@"-------------執行拷貝-------------");

[_collectionView?performBatchUpdates:^{

[_section0Array?removeObjectAtIndex:indexPath.row];

[_collectionView?deleteItemsAtIndexPaths:@[indexPath]];

}?completion:nil];

}

else?if([NSStringFromSelector(action)?isEqualToString:@"paste:"])

{

NSLog(@"-------------執行粘貼-------------");

}

}

二、自定義布局

UICollectionView自定義布局

要自定義UICollectionView布局,就要子類化UICollectionViewLayout,然后重寫它的一些方法以達到我們自定義布局的需求。下來我們來看看UICollectionViewLayout類里一些比較重要的方法:

- (void)prepareLayout;為layout顯示做準備工作,你可以在該方法里設置一些屬性。

- (CGSize)collectionViewContentSize;返回layout的size。

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect;返回在collectionView的可見范圍內(bounds)所有item對應的layoutAttrure對象裝成的數組。collectionView的每個item都對應一個專門的UICollectionViewLayoutAttributes類型的對象來表示該item的一些屬性,比如bounds,size,transform,alpha等。

- (UICollectionViewLayoutAttributes)layoutAttributesForItemAtIndexPath:(NSIndexPath)indexPath;傳入indexPath,返回該indexPath對應的layoutAtture對象。

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;當當前layout的布局發生變動時,是否重寫加載該layout。默認返回NO,若返回YES,則重新執行這倆方法:

- (void)prepareLayout;

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect;

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity;返回layout“最終”的偏移量,何謂“最終”,手指離開屏幕時layout的偏移量不是最終的,因為它有慣性,當它停止時才是“最終”偏移量。

自定義插入刪除動畫

插入刪除的操作

添加在哪觸發:

UIBarButtonItem?*btnItem?=?[[UIBarButtonItem?alloc]?initWithTitle:@"添加"

style:UIBarButtonItemStylePlain

target:self

action:@selector(addItemBtnClick:)];

self.navigationItem.rightBarButtonItem?=?btnItem;

添加的實現:

//?添加(插入item)

-?(void)addItemBtnClick:(UIBarButtonItem?*)btnItem

{

[_collectionView?performBatchUpdates:^{

//?構造一個indexPath

NSIndexPath?*indePath?=?[NSIndexPath?indexPathForItem:_section0Array.count?inSection:0];

[_collectionView?insertItemsAtIndexPaths:@[indePath]];?//?然后在此indexPath處插入給collectionView插入一個item

[_section0Array?addObject:@"x"];?//?保持collectionView的item和數據源一致

}?completion:nil];

}

因為是練習Demo,所以暫時把刪除的觸發源寫在了長按某Item彈出菜單的copy按鈕里。實際中你可以自定義UICollectionViewCell,添加長按手勢,長按抖動出現叉號,然后刪除等,隨你怎么做。

//?copy?and?paste?的實現

-?(void)collectionView:(UICollectionView?*)collectionView?performAction:(SEL)action?forItemAtIndexPath:(NSIndexPath?*)indexPath?withSender:(nullable?id)sender

{

if([NSStringFromSelector(action)?isEqualToString:@"copy:"])

{

//? ? ? ? NSLog(@"-------------執行拷貝-------------");

[_collectionView?performBatchUpdates:^{

[_section0Array?removeObjectAtIndex:indexPath.row];

[_collectionView?deleteItemsAtIndexPaths:@[indexPath]];

}?completion:nil];

}

else?if([NSStringFromSelector(action)?isEqualToString:@"paste:"])

{

NSLog(@"-------------執行粘貼-------------");

}

}

自定義轉場動畫

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,836評論 6 540
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,275評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,904評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,633評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,368評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,736評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,740評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,919評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,481評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,235評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,427評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,968評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,656評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,055評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,348評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,160評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,380評論 2 379

推薦閱讀更多精彩內容