不规则瀑布流

不规则瀑布流

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

3、瀑布流一共多少列

@property (nonatomic, assign) NSUInteger numberOfColumn;

//声明代理

@property (nonatomic, assign) id<WaterFlowLayoutDelegate>delegate;

@end

========================================================

4、在延展中分别声明一个存放每一列的高度和存放每一个item的属性 包含 frame 以及下标的可变数组

@interface WaterFlowLayout ()

//存放每一列的高度

@property (nonatomic, retain) NSMutableArray *columnHeightsArrary;

//存放每一个item的属性 包含 frame 以及下标

@property (nonatomic, retain) NSMutableArray *attributesArray;

@end

5、实现

@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);

    }

}

6、内容的范围

- (CGSize)collectionViewContentSize {

     NSLog(@"maxHeight = %f",[self maxHeight]);

    return CGSizeMake(self.collectionView.frame.size.width, [self maxHeight]);

}

7、加载属性的数组使其显示

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{

        return _attributesArray;

}

@end

原文地址:https://www.cnblogs.com/d-mm/p/5210171.html