CollectionView的組成
- cells
- Supplementary Views 追加視圖,(類似于header和footer)
- Decoration Views 裝飾視圖
UICollectionViewLayoutAttributes
UICollectionViewLayoutAttributes
property列表:
//邊框
@property (nonatomic) CGRect frame
//中心點(diǎn)
@property (nonatomic) CGPoint center
//大小
@property (nonatomic) CGSize size
//形狀
@property (nonatomic) CATransform3D transform3D
//透明度
@property (nonatomic) CGFloat alpha
//層次
@property (nonatomic) NSInteger zIndex
//隱藏
@property (nonatomic, getter=isHidden) BOOL hidden
自定義UICollectionViewLayout
-(CGSize)collectionViewContentSize
//返回collectionView的內(nèi)容的尺寸
-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
//返回rect中的所有的元素的布局屬性
//可以通過(guò)不同方法獲得cell,追加視圖舱呻,裝飾視圖的屬性
-(UICollectionViewLayoutAttributes _)layoutAttributesForItemAtIndexPath:(NSIndexPath _)indexPath
//返回對(duì)應(yīng)于indexPath的位置的cell的布局屬性
-(UICollectionViewLayoutAttributes _)layoutAttributesForSupplementaryViewOfKind:(NSString _)kind atIndexPath:(NSIndexPath *)indexPath
//返回對(duì)應(yīng)于indexPath的位置的追加視圖的布局屬性芥驳,如果沒(méi)有追加視圖可不重載
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
//當(dāng)邊界發(fā)生改變時(shí)兆旬,是否應(yīng)該刷新布局。如果YES則在邊界變化(一般是scroll到其他地方)時(shí)脚祟,將重新計(jì)算需要的布局信息
實(shí)例化一個(gè)UICollectionViewLayout后由桌,-(void)prepareLayout將被調(diào)用,默認(rèn)的情況下不做什么工作娃循,自己實(shí)現(xiàn)時(shí)設(shè)定一些必要的layout結(jié)構(gòu)和初始化參數(shù)。
下面是一個(gè)Demo
layout的.h文件
//高度代理
@class LFCLayout;
@protocol LFCCellHeightDelegate <NSObject>
-(CGFloat)LFCLayout:(LFCLayout*)layout cellHeightAtIndexPath:(NSIndexPath*)indexPath;
@end
@interface LFCLayout : UICollectionViewLayout
//行間距
@property (nonatomic,assign) CGFloat rowPadding;
//列間距
@property (nonatomic,assign) CGFloat colPadding;
//列數(shù)
@property (nonatomic,assign) CGFloat colNum;
//collectionView contentSize
@property (nonatomic,assign) CGSize contentSize;
@property (nonatomic,assign) UIEdgeInsets sectionInsets;
@property (nonatomic,weak) id<LFCCellHeightDelegate> delegate;
@end
.m文件
-(void)prepareLayout{
[super prepareLayout];
if (self.attributes == nil) {
self.attributes = [NSMutableArray array];
}
if (self.heightOfColArray == nil) {
self.heightOfColArray = [NSMutableArray array];
}
RowPadding = self.rowPadding == 0 ? RowPadding : self.rowPadding;
ColPadding = self.colPadding == 0 ? ColPadding : self.colPadding;
ColNum = self.colNum == 0 ? ColNum : self.colNum;
edge = self.sectionInsets;
//初始化每一列的高度
[self.heightOfColArray removeAllObjects];
for (NSInteger i = 0; i < ColNum; i++) {
[self.heightOfColArray addObject:@(edge.top)];
}
//獲取layoutattribute
NSInteger count = [self.collectionView numberOfItemsInSection:0];
for (NSInteger i = 0; i < count; i++) {
NSIndexPath* indexPath = [NSIndexPath indexPathForItem:i inSection:0];
UICollectionViewLayoutAttributes* attribute = [self layoutAttributesForItemAtIndexPath:indexPath];
[self.attributes addObject:attribute];
}
}
//返回對(duì)應(yīng)于indexPath的位置的cell的布局屬性
-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewLayoutAttributes* attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
//定義每個(gè)cell的寬和高
CGFloat width = (self.collectionView.bounds.size.width - edge.left - edge.right - (ColNum - 1) * RowPadding) / ColNum;
CGFloat height = 0;
//判斷delegate對(duì)象是否有該名字的方法,返回每個(gè)cell的高度
if ([self.delegate respondsToSelector:@selector(LFCLayout:cellHeightAtIndexPath:)]) {
height = [self.delegate LFCLayout:self cellHeightAtIndexPath:indexPath];
}
//默認(rèn)第一列高度最低
CGFloat minY = self.heightOfColArray.count ? [[self.heightOfColArray firstObject] floatValue] : edge.top;
//找出高度最低的那一列
NSInteger currentLow = 0;
for (NSInteger i = 1; i < self.heightOfColArray.count; i++) {
if (minY > [self.heightOfColArray[i] floatValue]) {
minY = [self.heightOfColArray[i] floatValue];
currentLow = i;
}
}
//找出之后即可定義每個(gè)cell的坐標(biāo)位置以及大小
CGFloat x = edge.left + (width + RowPadding) * currentLow;
CGFloat y = minY + edge.top;
attribute.frame = CGRectMake(x, y, width, height);
self.heightOfColArray[currentLow] = @(CGRectGetMaxY(attribute.frame));
//找出最高的一列的高度,設(shè)定contentSize;
CGFloat maxY = self.heightOfColArray.count ? [[self.heightOfColArray firstObject] floatValue] : edge.top;
for (NSInteger i = 1; i < self.heightOfColArray.count; i++) {
if (maxY < [self.heightOfColArray[i] floatValue]) {
maxY = [self.heightOfColArray[i] floatValue];
}
}
self.contentSize = CGSizeMake(self.collectionView.bounds.size.width, maxY + edge.bottom);
return attribute;
}
之前的Demo的圖片為同步加載
cell.imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]]];
,所以scroll會(huì)有卡頓柱嫌,將圖片改為異步加載编丘,并且在第一次加載后將其放置在本地索守,再次取用時(shí)直接從本地取用卵佛。
菜鳥(niǎo)剛剛起步截汪。渺尘。丢郊。參考其他人代碼,然后自己自己加了注解敲了一遍
如有錯(cuò)誤的地方希望大家可以指正拟淮。
[GitHub]https://github.com/superLFC/CollectionViewLayoutDemo