1.概況:
UICollectionView自iOS6.0以后就有了這個組件.以前還考慮著不敢用.不過隨著iOS9的到來,除了少量項目因為歷史原因以外,大部分項目都應(yīng)該支持iOS7以上了吧.所以,大膽使用.
初識UICollectionView,蠻復(fù)雜的,很多概念,什么Supplementary View,什么Decoration View.不過不用怕,它就是一個靈活版的UITableView.
UITableView大家很熟悉.就是定義一個table view,實現(xiàn)一個數(shù)據(jù)源的代理即可:告訴這個table view一共有多少個section,每個section有多少個row,每個row應(yīng)該怎么顯示就ok.
UICollectionView也是同樣的.定義一個collection view,實現(xiàn)一個數(shù)據(jù)源代理:告訴這個collection view一共有多少個section,每個section有多少個row,每個row應(yīng)該怎么顯示.
2.一個簡單的grid排版:
在這里我們使用xib
拖入一個UICollectionView.
同UITableView一樣,我們通過連線將其data source和delegate設(shè)置為其owner.
然后在view controller里面實現(xiàn)代理方法,告訴collection view具體有多少個cell:
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
迄今為止,使用方式上沒有任何和table view不一樣的地方.當(dāng)然了,api本身有一定的區(qū)別=.=
接下來,同UITableview一樣的是,我們需要實現(xiàn)該方法,以告訴collection view每個cell怎么顯示:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
我們可以建立UICollectionViewCell的子類,然后通過collection view進行注冊使用:
- (void)registerClass:(Class)cellClass forCellWithReuseIdentifier:(NSString *)identifier;
- (void)registerNib:(UINib *)nib forCellWithReuseIdentifier:(NSString *)identifier;
和UITableView一模一樣啊.
好了,不一樣的地方來了.UITableView需要一個代理告訴它每一個cell有多高,默認44.而每一個cell的長度就是table view本身的長度,所以每一個cell的size的width為table view本身的width,高度為代理的高度(默認44).
而collection view則要靈活很多,我們可以任意指定每一個cell的size,甚至是frame.基于目前的這個grid排版,我們可以用代理來指定每一個cell的size:
- 引入UICollectionViewDelegateFlowLayout,它繼承自UICollectionViewDelegate
- 也可以不引入該代理.只要有UICollectionViewDelegate,其代理方法就有效.引入于不引入的區(qū)別就是xCode是否會自動提示相關(guān)代碼.
- 實現(xiàn)代理中的方法方法.蘋果SDK的命名習(xí)慣帶來的最大的好處,就是你一眼就能看懂方法是什么意思.
更為簡便的是直接設(shè)置xib中的屬性,如圖:
通俗易懂,cell/header/footer的size,min spaceing等/xib可見即所得,隨意修改一下數(shù)字,就會產(chǎn)生變化.應(yīng)該很容易上手.
設(shè)置完畢以后,一個grid的排版就完了...以前table view要處理很多的,現(xiàn)在一下子就能搞定..真是很強大.
剩下的工作,你可以查看UICollectionViewDataSource等幾個代理方法.基本上代理的方法能滿足絕大部分需求了.
3.一些稍復(fù)雜的概念:
Supplementary View約等于table view中的section header/footer,是一個類型為:UICollectionReusableView的東西.在UICollectionView中,判定是header還是footer的依據(jù)是一個叫做kind的東西,kind是一個const字符串:
UICollectionElementKindSectionHeader
UICollectionElementKindSectionFooter.
UICollectionView的核心在于一個叫做UICollectionViewLayout的東西.由他來決定整個UICollectionView的方方面面.UICollectionViewLayout一個大的行為Model,它主要控制著整個collection view的布局/行為/顯示等邏輯.
在xib上直接拖入的UICollectionView,默認使用了UICollectionViewFlowLayout,SDK內(nèi)置的一個layout.
而UICollectionViewLayout中最最最核心的數(shù)據(jù)模型是一個叫做:UICollectionViewLayoutAttributes的東西.它存儲了每一個cell的數(shù)據(jù)模型,包括frame,center,size,transform,alpha等等.也就是說它決定了一個cell在什么地方以怎樣的形式顯示.而我們自定義的cell主要決定在某個確切的地方,這個cell展示的內(nèi)容.
復(fù)雜的collection view,通常會自定義UICollectionViewLayout.在自定義的UICollectionViewLayout里面.有2個方法非常核心,我們需要重載他.
根據(jù)table view的思路,我們可以先思考一下.
table view是個scroll view,可以滑動.那么一定是有一個content size的概念.table view的content size是多少呢?我們可以根據(jù)代理來計算.我們知道數(shù)據(jù)源的個數(shù)以及每一個cell的高度,那么content size通過計算就很容易得出了.
而當(dāng)我們滑動table view的時候,table view又怎么知道應(yīng)該顯示什么內(nèi)容呢?原理很簡單,因為table view是scroll view,所以可以知道當(dāng)前的content offset.通過數(shù)據(jù)源及每一cell的高度,結(jié)合content offset就知道當(dāng)前顯示到哪一行了.
可是自定義UICollectionViewLayout的UICollectionView并不知道這些數(shù)據(jù)(每個cell的size,frame均可以自定義),所以他就無法自動計算content size以及當(dāng)前應(yīng)該展示哪些cell.
所以我們就需要通過重載方法告訴它:
告訴它應(yīng)該有多少content size
- (CGSize)collectionViewContentSize
告訴他針對任意時刻,collection view應(yīng)該展示那些數(shù)據(jù).rect表示當(dāng)前可以被看到的區(qū)域,返回值是一個array,表示可以展示的數(shù)據(jù)是一個集合.
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
有了這2個方法,collection view就可以知道,自己的content size有多大.就可以痛快的滑動了.并且在滑動的過程中,就可以知道,應(yīng)該如何展示數(shù)據(jù)了.
4.實戰(zhàn)一個自定義UICollectionViewLayout
下一篇來嘗試一個簡單的自定義layout,如下圖.