单军华
2018-07-11 7b02207537d35bfa1714bf8beafc921f717d100a
screendisplay/screendisplay/Classes/Base/BaseView/LMJHorizontalFlowLayout.m
New file
@@ -0,0 +1,219 @@
//
//  LMJHorizontalFlowLayout.m
//  瀑布流完善接口
//
//  Created by apple on 16/7/31.
//  Copyright © 2016年 NJHu. All rights reserved.
//
#import "LMJHorizontalFlowLayout.h"
#define LMJXX(x) floorf(x)
#define LMJXS(s) ceilf(s)
static const NSInteger LMJ_Lines_ = 3;
static const CGFloat LMJ_XMargin_ = 10;
static const CGFloat LMJ_YMargin_ = 10;
static const UIEdgeInsets LMJ_EdgeInsets_ = {10, 10, 10, 10};
@interface LMJHorizontalFlowLayout()
/** 所有的cell的attrbts */
@property (nonatomic, strong) NSMutableArray<UICollectionViewLayoutAttributes *> *lmj_AtrbsArray;
/** 每一列的最后的高度 */
@property (nonatomic, strong) NSMutableArray<NSNumber *> *lmj_LinesWidthArray;
- (NSInteger)lines;
- (CGFloat)xMarginAtIndexPath:(NSIndexPath *)indexPath;
- (CGFloat)yMargin;
- (UIEdgeInsets)edgeInsets;
@end
@implementation LMJHorizontalFlowLayout
/**
 *  刷新布局的时候回重新调用
 */
- (void)prepareLayout
{
    [super prepareLayout];
    //如果重新刷新就需要移除之前存储的高度
    [self.lmj_LinesWidthArray removeAllObjects];
    //复赋值以顶部的高度, 并且根据行数
    for (NSInteger i = 0; i < self.lines; i++) {
        [self.lmj_LinesWidthArray addObject:@(self.edgeInsets.left)];
    }
    // 移除以前计算的cells的attrbs
    [self.lmj_AtrbsArray removeAllObjects];
    // 并且重新计算, 每个cell对应的atrbs, 保存到数组
    for (NSInteger i = 0; i < [self.collectionView numberOfItemsInSection:0]; i++)
    {
        [self.lmj_AtrbsArray addObject:[self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]]];
    }
}
/**
 *在这里边所处每个cell对应的位置和大小
 */
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewLayoutAttributes *atrbs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    CGFloat h = 1.0 * (self.collectionView.frame.size.height - self.edgeInsets.top - self.edgeInsets.bottom - self.yMargin * (self.lines - 1)) / self.lines;
    h = LMJXX(h);
    // 宽度由外界决定, 外界必须实现这个方法
    CGFloat w = [self.delegate waterflowLayout:self collectionView:self.collectionView widthForItemAtIndexPath:indexPath itemHeight:h];
    // 拿到最后的高度最小的那一列, 假设第0列最小
   __block NSInteger indexLine = 0;
   __block CGFloat minLineW = [self.lmj_LinesWidthArray[indexLine] doubleValue];
    [self.lmj_LinesWidthArray enumerateObjectsUsingBlock:^(NSNumber * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        CGFloat lineW = obj.doubleValue;
        if(minLineW > lineW)
        {
            minLineW = lineW;
            indexLine = idx;
        }
    }];
    CGFloat x = [self xMarginAtIndexPath:indexPath] + minLineW;
    if (minLineW == self.edgeInsets.left) {
        x = self.edgeInsets.left;
    }
    CGFloat y = self.edgeInsets.top + (self.yMargin + h) * indexLine;
    // 赋值frame
    atrbs.frame = CGRectMake(x, y, w, h);
    // 覆盖添加完后那一列;的最新宽度
    self.lmj_LinesWidthArray[indexLine] = @(CGRectGetMaxX(atrbs.frame));
    return atrbs;
}
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
    return self.lmj_AtrbsArray;
}
- (CGSize)collectionViewContentSize
{
   __block CGFloat maxColW = [self.lmj_LinesWidthArray[0] doubleValue];
    [self.lmj_LinesWidthArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if (maxColW < [obj doubleValue]) {
            maxColW = [obj doubleValue];
        }
    }];
    return CGSizeMake(maxColW + self.edgeInsets.right, self.collectionView.frame.size.height);
}
- (NSMutableArray *)lmj_AtrbsArray
{
    if(_lmj_AtrbsArray == nil)
    {
        _lmj_AtrbsArray = [NSMutableArray array];
    }
    return _lmj_AtrbsArray;
}
- (NSMutableArray *)lmj_LinesWidthArray
{
    if(_lmj_LinesWidthArray == nil)
    {
        _lmj_LinesWidthArray = [NSMutableArray array];
    }
    return _lmj_LinesWidthArray;
}
- (NSInteger)lines
{
    if([self.delegate respondsToSelector:@selector(waterflowLayout:linesInCollectionView:)])
    {
        return [self.delegate waterflowLayout:self linesInCollectionView:self.collectionView];
    }
    else
    {
        return LMJ_Lines_;
    }
}
- (CGFloat)xMarginAtIndexPath:(NSIndexPath *)indexPath
{
    if([self.delegate respondsToSelector:@selector(waterflowLayout:collectionView:columnsMarginForItemAtIndexPath:)])
    {
        return [self.delegate waterflowLayout:self collectionView:self.collectionView columnsMarginForItemAtIndexPath:indexPath];
    }
    else
    {
        return LMJ_XMargin_;
    }
}
- (CGFloat)yMargin
{
    if([self.delegate respondsToSelector:@selector(waterflowLayout:linesMarginInCollectionView:)])
    {
        return [self.delegate waterflowLayout:self linesMarginInCollectionView:self.collectionView];
    }else
    {
        return LMJ_YMargin_;
    }
}
- (UIEdgeInsets)edgeInsets
{
    if([self.delegate respondsToSelector:@selector(waterflowLayout:edgeInsetsInCollectionView:)])
    {
        return [self.delegate waterflowLayout:self edgeInsetsInCollectionView:self.collectionView];
    }
    else
    {
        return LMJ_EdgeInsets_;
    }
}
- (id<LMJHorizontalFlowLayoutDelegate>)delegate
{
    return (id<LMJHorizontalFlowLayoutDelegate>)self.collectionView.dataSource;
}
- (instancetype)initWithDelegate:(id<LMJHorizontalFlowLayoutDelegate>)delegate
{
    if (self = [super init]) {
    }
    return self;
}
+ (instancetype)flowLayoutWithDelegate:(id<LMJHorizontalFlowLayoutDelegate>)delegate
{
    return [[self alloc] initWithDelegate:delegate];
}
@end