//CollectionView會(huì)在初次布局時(shí)首先調(diào)用該方法
//CollectionView會(huì)在布局失效后、重新查詢布局之前調(diào)用此方法
//子類中必須重寫該方法并調(diào)用超類的方法
- (void)prepareLayout;
//子類必須重寫此方法。
//并使用它來(lái)返回CollectionView視圖內(nèi)容的寬高,
//這個(gè)值代表的是所有的內(nèi)容的寬高,并不是當(dāng)前可見(jiàn)的部分。
//CollectionView將會(huì)使用該值配置內(nèi)容的大小來(lái)促進(jìn)滾動(dòng)。
- (CGRect)collectionViewContentSize;
// UICollectionView 調(diào)用以下四個(gè)方法來(lái)確定布局信息
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect; // return an array layout attributes instances for all the views in the given rect
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath;
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString*)elementKind atIndexPath:(NSIndexPath *)indexPath;
//當(dāng)Bounds改變時(shí),返回YES使CollectionView重新查詢幾何信息的布局
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;
自定義UICollectionView,主要會(huì)用到以下幾個(gè)方法:
- (void)prepareLayout;
第一次加載layout、刷新layout、以及- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;這個(gè)方法返回yes時(shí),會(huì)調(diào)用。這是蘋果官方的說(shuō)明The collection view calls -prepareLayout once at its first layout as the first message to the layout instance. The collection view calls -prepareLayout again after layout is invalidated and before requerying the layout information. Subclasses should always call super if they override。實(shí)現(xiàn)該方法后應(yīng)該調(diào)用[super prepareLayout]保證初始化正確。該方法用來(lái)準(zhǔn)備一些布局所需要的信息。該方法和init方法相似,但該方法可能會(huì)被調(diào)用多次,所以一些不固定的計(jì)算(比如該計(jì)算和collectionView的尺寸相關(guān)),最好放在這里,以保證collectionView發(fā)生變化時(shí),自定義CollectionView能做出正確的反應(yīng)。
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;
該方法用來(lái)返回rect范圍內(nèi)的 cell supplementary 以及 decoration的布局屬性layoutAttributes(這里保存著她們的尺寸,位置,indexPath等等),如果你的布局都在一個(gè)屏幕內(nèi) 活著 沒(méi)有復(fù)雜的計(jì)算,我覺(jué)得這里可以返回全部的屬性數(shù)組,如果涉及到復(fù)雜計(jì)算,應(yīng)該進(jìn)行判斷,返回區(qū)域內(nèi)的屬性數(shù)組,有時(shí)候?yàn)榱朔奖阒苯臃祷亓巳康膶傩詳?shù)組,不影響布局但可能會(huì)影響性能(如果你的item一屏幕顯示不完,那么這個(gè)方法會(huì)調(diào)用多次,當(dāng)所有的item都加載完畢后,在滑動(dòng)collectionView時(shí)不會(huì)調(diào)用該方法的)。
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
該方法不是必須實(shí)現(xiàn)的,即便你實(shí)現(xiàn)了,我們對(duì)collectionView的任何操作,也不會(huì)導(dǎo)致系統(tǒng)主動(dòng)調(diào)用該方法。該方法通常用來(lái)定制某個(gè)IndexPath的item的屬性。當(dāng)然我們也可以重寫這個(gè)方法,將布局時(shí)相關(guān)的屬性設(shè)置放在這里,在- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect 或者 - (void)prepareLayout 中 需要?jiǎng)?chuàng)建用來(lái)返回給系統(tǒng)的屬性數(shù)組 主動(dòng)調(diào)用這個(gè)方法,并添加帶可變數(shù)組中去返回給系統(tǒng)。當(dāng)然我們也可以在 - (void)prepareLayout 中 通過(guò)[UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForRow:i inSection:0]] 獲取 每個(gè)indexPath的attributes,在- (void)prepareLayout中設(shè)置所有item的屬性??葱枨笠约皞€(gè)人喜歡。
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;
用來(lái)刷新layout的,當(dāng)我們返回yes的時(shí)候。如果我們的需求不需要實(shí)時(shí)的刷新layout,那么最好判斷newBounds 和 我們的collectionView的bounds是否相同,不同時(shí)返回yes;(例如蘋果官方的lineLayout,因?yàn)槊看位瑒?dòng)都要放大item,所以這了就直接返回yes)。
以蘋果官方的lineLayout為例,這個(gè)是對(duì)UICollectionViewFlowLayout的擴(kuò)充,