自定义瀑布流WaterPullLayout

自定义瀑布流

//
//  WaterPullLayout.m
//  瀑布流
//
//  Created by qianfeng on 16/8/29.
//  Copyright © 2016年 qianfeng. All rights reserved.
//

#import "WaterPullLayout.h"
#import "Model.h"

@interface WaterPullLayout ()
/**
 *  保存每列的总高度
 */
@property (nonatomic, strong) NSMutableArray *columnHeightArray;
/**
 *  保存cell详细信息
 */
@property (nonatomic, strong) NSMutableArray *itemAttributes;
@end




@implementation WaterPullLayout
-(instancetype)init
{
    if (self = [super init]) {
        /** 默认值 */
        _column = 2; //列数
        _sectionInsets = UIEdgeInsetsZero;  //内边距
        _lineSpacing = 10; //行间距
        _interitemSpacing = 10; //列间距
    }
    return self;
}



#pragma mark - 自定义Layout四部曲
/**
 *  1.布局cell,如果调用collectionView的reloaddata方法会触发该方法(相当于UItableView自定义控件中的LayoutSubViews)
 */
-(void)prepareLayout{
    //初始化数组
    _columnHeightArray = [NSMutableArray array];
    _itemAttributes = [NSMutableArray array];
    //添加默认值,每列高度默认是0
    for (int i = 0; i < self.column; i++)
    {
        [_columnHeightArray addObject:@(0)];
    }
    /** 对每个cell位置进行计算 */
    CGFloat xOffset;
    CGFloat yOffset;
    CGFloat itemWidth;
    CGFloat itemHeight;
    
    /** cell的宽度 */
    itemWidth = (CGRectGetWidth(self.collectionView.frame) - self.sectionInsets.left - self.sectionInsets.right - _interitemSpacing * (_column - 1) ) / _column;
    
    /** 组的个数 */
    //[self.collectionView numberOfSections];
    
    /** 每个组的cell的个数 */
    NSInteger numberofItems = [self.collectionView numberOfItemsInSection:0];
    
    /** 控制显示每个cell */
    for (NSInteger i = 0; i < numberofItems; i ++) {
        
        Model *model = self.datasourceArray[i];
        /** 现在的高度 */
        itemHeight = model.h  * itemWidth / model.w;
        /** 最小列的 index */
        NSInteger minIndex = [self minIndexFromColumnHeightArray];
        /** X */
        xOffset = _sectionInsets.left + minIndex * (itemWidth + _interitemSpacing);
        /** Y */
        yOffset = (i < _column) ? _sectionInsets.top : ([_columnHeightArray[minIndex] floatValue] + _lineSpacing);
        
        
        /** 创建item的attribute对象 */
        UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
        attributes.frame = CGRectMake(xOffset, yOffset, itemWidth, itemHeight);
        [self.itemAttributes addObject:attributes]; //保存item的属性信息
        
        /** 修改数组中当前的最小高度 */
        _columnHeightArray[minIndex] = @(CGRectGetMaxY(attributes.frame));
    }
}

/**
 *  2.返回指定范围的cell的布局的详细信息
 *
 *  @param rect <#rect description#>
 *
 *  @return <#return value description#>
 */
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
    return self.itemAttributes;
}

/**
 *  3.返回指定的cell的详细布局信息
 *
 *  @param indexPath <#indexPath description#>
 *
 *  @return <#return value description#>
 */
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return self.itemAttributes[indexPath.item];
}

/**
 *  4.重新计算当前滚动视图的contentSize
 *
 *  @return <#return value description#>
 */
- (CGSize)collectionViewContentSize
{
    //获取最大列的index
    NSUInteger maxIndex = [self maxIndexFromColumnHeightArray];
    
    return CGSizeMake(self.collectionView.frame.size.width, [_columnHeightArray[maxIndex] floatValue] + _sectionInsets.bottom);
}


#pragma mark - 普通Action
/**
 *   求高度最小列的index
 */
-(NSInteger)minIndexFromColumnHeightArray
{
    __block NSInteger minIndex = 0;
    
    __block CGFloat min = MAXFLOAT;
    
    [_columnHeightArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
       
        /** 如果在当前数组有比当前数组还小的数,说明这个数就是最小值 */
        if (min > [obj floatValue]) {
            
            min = [obj floatValue];
            
            minIndex = idx;
        }
    }];
    return minIndex;
}
/**
 *  返回高度最大的列index
 */
- (NSInteger)maxIndexFromColumnHeightArray
{
    __block NSInteger maxIndex = 0;
    //min=MAXFLOAT目的为了保证第一个值一定为最小值
    __block CGFloat max = 0;
    
    //遍历
    [_columnHeightArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
        //如果当前数组中有比当前最小值还小的数,说明当前这个数就是最小值
        if (max < [obj floatValue])
        {
            //保存最小值
            max = [obj floatValue];
            //保存最下值的索引
            maxIndex = idx;
        }
    }];
    
    return maxIndex;
}

@end


此资源快速下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值