不规则瀑布流
1、创建一个继承自UICollectionViewLayout
//说明WaterFlowLayout是一个类
@class WaterFlowLayout;
2、声明协议(实际上就是UICollectionViewDelegate中的协议,将UICollectionViewLayout*换成了自定义的WaterFlowLayout*)
@protocol WaterFlowLayoutDelegate<NSObject>
//关键方法,此方法的作用是返回每一个Item的size的大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(WaterFlowLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;
//item间 的间隙大小
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(WaterFlowLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;
//每行的行间距
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(WaterFlowLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section;
//扩展空间的大小
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(WaterFlowLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section;
@end
@interface WaterFlowLayout : UICollectionViewLayout
2、瀑布流一共多少列
@property (nonatomic, assign) NSUInteger numberOfColumn;
//声明代理
@property (nonatomic, assign) id<WaterFlowLayoutDelegate>delegate;
@end
3、在延展中分别声明一个存放每一列的高度和存放每一个item的属性 包含 frame 以及下标的可变数组
@interface WaterFlowLayout ()
//存放每一列的高度
@property (nonatomic, retain) NSMutableArray *columnHeightsArrary;
//存放每一个item的属性 包含 frame 以及下标
@property (nonatomic, retain) NSMutableArray *attributesArray;
@end
4、实现
@implementation WaterFlowLayout
(1)//获取最小高度的方法
- (CGFloat)minHeight {
CGFloat min = 100000;
for (NSNumber *height in _columnHeightsArrary) {
CGFloat h = [height floatValue];
if (min > h) {
min = h;
}
}
// NSLog(@"min = %f", min);
return min;
}
(2)//获取最大值
- (CGFloat)maxHeight {
CGFloat max = 0;
for (NSNumber *height in _columnHeightsArrary) {
CGFloat h = [height floatValue];
if (max < h) {
max = h;
}
}
return max;
}
(3)//记录最小高度的下标
- (NSUInteger)indexOfMinHeight {
NSUInteger index = 0;
for (int i = 0; i < _columnHeightsArrary.count; i ++) {
CGFloat height = [[_columnHeightsArrary objectAtIndex:i] floatValue];
if (height == [self minHeight]) {
index = i;
NSLog(@"index = %d",i);
return i;
}
}
return index;
}
(4)//重写父类的布局方法
- (void)prepareLayout {
[super prepareLayout];
_columnHeightsArrary = [[NSMutableArray alloc] initWithCapacity:0];
_attributesArray = [[NSMutableArray alloc] initWithCapacity:0];
//给 列高数组 里面的对象赋初值
for (int i = 0; i < self.numberOfColumn; i ++) {
[_columnHeightsArrary addObject:@0.0];
}
CGFloat totalWidth = self.collectionView.frame.size.width;
NSLog(@"totalWidth = %f",self.collectionView.frame.size.width);
//创建 每个人item frame中的 x、y
CGFloat x = 0;
CGFloat y = 0;
//获取0分区下所有的item数
NSUInteger itemCount = [self.collectionView numberOfItemsInSection:0];//################
NSLog(@"itemCount = %lu",itemCount);
for (int i = 0; i < itemCount; i ++) {
//得到集合视图中, 列间隙的个数
NSUInteger numberOfSpace = self.numberOfColumn - 1;
//代理对象执行代理方法, 得到 item 之间的间隙大小
CGFloat spaceWidth = [_delegate collectionView:self.collectionView layout:self minimumInteritemSpacingForSectionAtIndex:0];//##############
NSLog(@"spaceWidth = %f", spaceWidth);
//求每列的宽度,也就是每一个item的width
CGFloat width = (totalWidth - spaceWidth * numberOfSpace) / self.numberOfColumn;
//**************获取每一个itemSize的大小*********************
//构建位置信息
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
//数据中原始图片的大小
CGSize imageSize = [_delegate collectionView:self.collectionView layout:self sizeForItemAtIndexPath:indexPath];
//通过 约分公式得到固定宽之后的高度是多少
CGFloat height = width * imageSize.height / imageSize.width;
//求列高最小的那一列的下标
NSUInteger minHeightIndex = [self indexOfMinHeight];
//求出最小列的高度
CGFloat minHeight = [_columnHeightsArrary[minHeightIndex] floatValue];
//求出行高
CGFloat lineHeight = [_delegate collectionView:self.collectionView layout:self minimumLineSpacingForSectionAtIndex:0];
//上次总的高度 加上 行高 加上新加上的item的height, 才是现在这一列的总高度
//minHeight为最小列现在的高度
//lineHeight为行间距
//height为新加的item
_columnHeightsArrary[minHeightIndex] = [NSNumber numberWithFloat:minHeight + lineHeight + height];
//*******************************************************
UICollectionViewLayoutAttributes *attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
//记录每一个item的大小和位置
attribute.frame = CGRectMake(x, y, width, height);
//数组保存每一个item的位置信息
[_attributesArray addObject:attribute];
//*******************************************************
//重新算最小列高的下标
minHeightIndex = [self indexOfMinHeight];
NSLog(@"minHeightIndex = %lu",[self indexOfMinHeight]);
//计算一次新加的item的x和y的值
x = (spaceWidth + width) * minHeightIndex;
NSLog(@"x = %f",x);
y = [self minHeight];
NSLog(@"y = %f",y);
}
}
5、内容的范围
- (CGSize)collectionViewContentSize {
NSLog(@"maxHeight = %f",[self maxHeight]);
return CGSizeMake(self.collectionView.frame.size.width, [self maxHeight]);
}
6、加载属性的数组使其显示
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{
return _attributesArray;
}
@end