關(guān)鍵方法
-
1
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect掌呜;
該方法用來返回rect范圍內(nèi)的 cell supplementary 以及 decoration的布局屬性layoutAttributes(這里保存著她們的尺寸注簿,位置捉片,indexPath等等),如果你的布局都在一個屏幕內(nèi)或者沒有復(fù)雜的計算惰说,這里可以返回全部的屬性數(shù)組性誉,如果涉及到復(fù)雜計算豁鲤,應(yīng)該進行判斷,返回區(qū)域內(nèi)的屬性數(shù)組惫恼,有時候為了方便直接返回了全部的屬性數(shù)組档押,不影響布局但可能會影響性能(如果你的item一屏幕顯示不完,那么這個方法會調(diào)用多次,當所有的item都加載完畢后令宿,在滑動collectionView時不會調(diào)用該方法的)叼耙。
-
2
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
該方法不是必須實現(xiàn)的粒没,即便你實現(xiàn)了筛婉,我們對collectionView的任何操作,也不會導(dǎo)致系統(tǒng)主動調(diào)用該方法癞松。該方法通常用來定制某個IndexPath的item的屬性爽撒。當然我們也可以重寫這個方法,將布局時相關(guān)的屬性設(shè)置放在這里拦惋,在
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
或者- (void)prepareLayout
中 需要創(chuàng)建用來返回給系統(tǒng)的屬性數(shù)組 主動調(diào)用這個方法匆浙,并添加帶可變數(shù)組中去返回給系統(tǒng)。當然我們也可以在- (void)prepareLayout
中 通過[UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForRow:i inSection:0]]
獲取 每個indexPath的attributes厕妖,在- (void)prepareLayout
中設(shè)置所有item的屬性首尼。看需求以及個人喜歡言秸。 -
3
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;
用來刷新layout的软能,當我們返回yes的時候。如果我們的需求不需要實時的刷新layout举畸,那么最好判斷newBounds 和 我們的collectionView的bounds是否相同查排,如果不同就返回yes;(例如蘋果官方的lineLayout抄沮,因為每次滑動都要放大item跋核,所以這了就直接返回yes)。
-
4
- (void)prepareLayout;
第一次加載layout叛买、刷新layout砂代、以及
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;
這個方法返回yes時,會調(diào)用率挣。實現(xiàn)該方法后應(yīng)該調(diào)用[super prepareLayout]
保證初始化正確刻伊。該方法用來準備一些布局所需要的信息。該方法和init方法相似椒功,但該方法可能會被調(diào)用多次捶箱,所以一些不固定的計算(比如該計算和collectionView的尺寸相關(guān)),最好放在這里动漾,以保證collectionView發(fā)生變化時丁屎,自定義CollectionView能做出正確的反應(yīng)。
舉例
需要展示大小不相等的幾張圖片
說明:圖片0比其他幾張圖片大旱眯,從而影響到布局悦屏,所以我們自定義一種布局
@interface SixImageLayout : UICollectionViewLayout
兩個關(guān)鍵方法
返回所有cell的布局
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
self.cellCount = 6; 共6個cell
NSMutableArray *attributes = [NSMutableArray array];
for (NSInteger i = 0; i < self.cellCount; i ++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
//調(diào)用下面的方法返回
UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexPath];
[attributes addObject:attrs];
}
return attributes;
}
計算每個位置的布局
- (UICollectionViewLayoutAttributes )layoutAttributesForItemAtIndexPath:(NSIndexPath )indexPath {
UICollectionViewLayoutAttributes attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
attributes.size = CGSizeMake(kCellSize, kCellSize);
if (indexPath.row == 0) {
attributes.size = CGSizeMake(kCellSize2+1, kCellSize2+1);
attributes.center = CGPointMake((kCellSize2+1)/2, (kCellSize2+1)/2);
}
else if (indexPath.row == 1) {
attributes.center = CGPointMake(kCellSize2+2+kCellSize/2, kCellSize/2);
} else if(indexPath.row == 2) {
attributes.center = CGPointMake(kCellSize2+2+kCellSize/2, kCellSize+kCellSize/2+1);
}else if (indexPath.row == 3) {
attributes.center = CGPointMake(kCellSize/2, kCellSize2+2+kCellSize/2);
} else if(indexPath.row == 4) {
attributes.center = CGPointMake(kCellSize+kCellSize/2+1, kCellSize2+2+kCellSize/2);
} else {
attributes.center = CGPointMake(kCellSize2+2+kCellSize/2, kCellSize*2+2+kCellSize/2);
}
return attributes;}
然后設(shè)置布局
SixImageLayout *sixLayout = [[SixImageLayout alloc] init];
self.collectionV = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 110, kScreenWidth, kScreenWidth) collectionViewLayout:sixLayout];