OC-创建瀑布流

1. 创建“WYWaterflowLayout”继承制  “UICollectionViewLayout”。

2. 在“ViewController” 中导入“WYWaterflowLayout”类。并创建,创建的代码如下

@property (nonatomic,weak) UICollectionView *collectionView;

- (void)CircleLayout
{
    WYWaterflowLayout *layout = [[WYWaterflowLayout alloc] init];
      
    // 创建CollectionView
    UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
    collectionView.dataSource = self;
    collectionView.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:collectionView];
    
    self.collectionView = collectionView;
    
    // 使用系统自带的类注册
   // [collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:WYShopID];
    
    // 使用自定义类注册
    [collectionView registerNib:[UINib nibWithNibName:NSStringFromClass([XMGShopCell class]) bundle:nil] forCellWithReuseIdentifier:WYShopID];
}

3. 数据源<UICollectionViewDataSource>

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    self.collectionView.footer.hidden = self.shops.count == 0;
    return self.shops.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{

    XMGShopCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:WYShopID forIndexPath:indexPath];
    XMGShop *shopses = self.shops[indexPath.item];
    cell.shop = shopses;
    
    return cell;
}

4. 写 “WYWaterflowLayout”的方法,这四个类是必须要写的。

// 初始化

- (void)prepareLayout;

// 决定cell的排布

- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;

// 返回indexPath位置cell对应的布局属性

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;

- (CGSize)collectionViewContentSize

 整体代码如下:

//
//  WYWaterflowLayout.m
//  瀑布流
//
//  Created by baojia on 16/8/26.
//  Copyright © 2016年 OS. All rights reserved.
//

#import "WYWaterflowLayout.h"

/** 默认的列数 */
static const NSInteger WYColumnCount = 3 ;
/** 每列之间的间距 */
static const CGFloat   WYColumnMargin = 10 ;
/** 每行之间的间距 */
static const CGFloat   WYRowMarage   = 20;
/** 边缘距离 */
static const UIEdgeInsets WYEdgeInsets = {10,10,10,10};


@interface WYWaterflowLayout ()
@property (nonatomic,strong) NSMutableArray   *attrsArray;
/** 存放所有列的当前高度 */
@property (nonatomic,strong) NSMutableArray   *columnHeights;

@end

@implementation WYWaterflowLayout
- (NSMutableArray *)columnHeights
{
    if (_columnHeights == nil)
    {
        _columnHeights = [NSMutableArray array];
    }
    return _columnHeights ;
}

- (NSMutableArray *)attrsArray
{
    if (_attrsArray == nil)
    {
        _attrsArray = [NSMutableArray array];
    }
    return _attrsArray ;
}

// 初始化
- (void)prepareLayout
{
    [super prepareLayout];
    
    // 清楚以前计算的所有高度
    [self.columnHeights removeAllObjects];
    
    for (NSInteger i = 0; i < WYColumnCount; i++) {
        [self.columnHeights addObject:@(WYEdgeInsets.top)];
    }

    // 清空之前所有的布局属性
    [self.attrsArray removeAllObjects];
    
    // 添加布局属性
    [self arrayPrepareLayout];

}

// 决定cell的排布
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
    // 这个方法会频繁的调用,每次这个界面进行滚动的时候都会调用这个方法,当这个类继承制“UICollectionViewLayout”的时候。
    // 瀑布流算好一遍就可以了,所以可以放在初始化中弄。
    
    return self.attrsArray;
}

// 返回indexPath位置cell对应的布局属性
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
    // 2. 创建布局属性
    UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    
    // collectionView的宽度
    CGFloat collectionView_W = self.collectionView.frame.size.width;
    
    // 3. 设置布局属性的frame
    CGFloat attrs_W = (collectionView_W - WYEdgeInsets.left - WYEdgeInsets.right - (WYColumnCount - 1) * WYColumnMargin) / WYColumnCount;
    CGFloat attrs_H = 50 + arc4random_uniform(100);
    
    /* 第一种方法
    // 3.1 找出高度最短的那一列
    __block NSInteger destColumn = 0 ;
    __block CGFloat minColumnHeight = MAXFLOAT;
    
    [self.columnHeights enumerateObjectsUsingBlock:^(NSNumber *columnHeightNumber, NSUInteger idx, BOOL * _Nonnull stop) {
        
        CGFloat columnHeight = columnHeightNumber.doubleValue;
        
        if (minColumnHeight > columnHeight) {
            minColumnHeight = columnHeight;
            destColumn = idx;
        }
    }];
     */
    
    // 第二种写法
    NSInteger destColumn = 0;
    CGFloat mincolumnHeight = [self.columnHeights[0] doubleValue];
    for (NSInteger i = 1; i < WYColumnCount; i++) {
        // 取得第一列的高度
        CGFloat columnHeight = [self.columnHeights[i] doubleValue];
        
        if (mincolumnHeight > columnHeight) {
            mincolumnHeight = columnHeight;
            destColumn = i;
        }
    }
    
 
    CGFloat attrs_X = WYEdgeInsets.left + destColumn * (attrs_W + WYColumnMargin);
    
    CGFloat attrs_Y = mincolumnHeight;
    if (attrs_Y != WYEdgeInsets.top) {
        attrs_Y += WYRowMarage;
    }
    
    attrs.frame = CGRectMake(attrs_X, attrs_Y, attrs_W, attrs_H);
    
    // 4. 更新最短那列的高度
    self.columnHeights[destColumn] = @(CGRectGetMaxY(attrs.frame));

    return attrs;
}

- (CGSize)collectionViewContentSize
{
    CGFloat maxColumnHeight = [self.columnHeights[0] doubleValue];
    for (NSInteger i = 1; i < WYColumnCount ; i++) {
        // 取得第i列额高度
        CGFloat columnHeight = [self.columnHeights[i] doubleValue];
        
        if (maxColumnHeight < columnHeight) {
            maxColumnHeight = columnHeight;
        }
    }
    return CGSizeMake(0, maxColumnHeight + WYEdgeInsets.bottom);
}

#pragma mark - cell的排布
- (NSMutableArray *)arrayPrepareLayout
{
    // 1. 创建一个数组(存放所有cell的布局属性)
//    NSMutableArray *arrayM = [NSMutableArray array];
    
    // 2. 开始创建每一个cell对应的布局属性
    NSInteger count = [self.collectionView numberOfItemsInSection:0];
    
    for (NSInteger i = 0 ; i < count;  i++) {
        // 1. 创建位置
        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
        
        // 2. 获取indexPath位置cell对应的布局
        UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexPath];
        [self.attrsArray addObject:attrs];
    }
    return self.attrsArray;
}
@end
原文地址:https://www.cnblogs.com/iOS363536404/p/5832804.html