iOS 瀑布流布局

版权声明:禁止转载、复制 https://blog.csdn.net/qq_37191821/article/details/85264252

自定义Layout继承UICollectionViewLayout类即可,代码如下:

#import <UIKit/UIKit.h>

@class ZJFallLayout;

@protocol ZJFallLayoutDelegate <NSObject>

@optional

// 列数

-(NSInteger)collectionView:(UICollectionView *)view layout:(ZJFallLayout *)layout columnCountForSectionAtIndex:(NSInteger)section;

// 行间距

-(CGFloat)collectionView:(UICollectionView *)view layout:(ZJFallLayout *)layout lineSpacingForSectionAtIndex:(NSInteger)section;

// 列间距

-(CGFloat)collectionView:(UICollectionView *)view layout:(ZJFallLayout *)layout columnSpacingForSectionAtIndex:(NSInteger)section;

// item大小

-(CGSize)collectionView:(UICollectionView *)view layout:(ZJFallLayout *)layout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;

// 边距

-(UIEdgeInsets)collectionView:(UICollectionView *)view layout:(ZJFallLayout *)layout insetForSectionAtIndex:(NSInteger)section;

@end

@interface ZJFallLayout : UICollectionViewLayout

@property (nonatomic, weak) id<ZJFallLayoutDelegate> delegate;

@end

#import "ZJFallLayout.h"

@interface ZJFallLayout()

///< 所有的cell的布局

@property (nonatomic, strong) NSMutableArray<UICollectionViewLayoutAttributes *> * attrsArray;

///<  key列 value maxY值

@property (nonatomic, strong) NSMutableDictionary * columnMaxY;

@end

static const CGFloat ZJDefaultColumnCount  = 3;                         ///< 默认列数

static const CGFloat ZJDefaultColumnMargin = 10;                        ///< 默认列边距

static const CGFloat ZJDefaultlineMargin   = 10;                        ///< 默认行边距

static const UIEdgeInsets ZJDefaultInsets  = {10, 10, 10, 10};          ///< 默认collectionView边距

@implementation ZJFallLayout

- (void)prepareLayout

{

    // 重写必须调用super方法

    [super prepareLayout];

    NSInteger columnCount   = [self columnCountWithIndexPath:0];

    UIEdgeInsets edgeInsets = [self edgeInsetsWithIndexPath:0];

    for(int i=0;i<columnCount;i++){

        NSString * columKey = [NSString stringWithFormat:@"%d",i];

        [[self columnMaxY] setValue:@(edgeInsets.top) forKey:columKey];

    }

    // 遍历所有的cell,计算所有cell的布局

    [[self attrsArray] removeAllObjects];

    for (NSInteger i = 0; i < [self.collectionView numberOfItemsInSection:0]; i++) {

        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];

        // 计算布局属性并将结果添加到布局属性数组中

        @autoreleasepool{

            [self.attrsArray addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];

        }

    }

    //NSLog(@" > > > > > > > ");

}

// 返回布局属性,一个UICollectionViewLayoutAttributes对象数组

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

{

    return self.attrsArray;

}

//设置collectionView滚动区域

-(CGSize)collectionViewContentSize

{

    //假设最长的那一列为第0列

    __block NSString *maxColumn = @"0";

    

    //遍历字典,找出最长的那一列

    [self.columnMaxY enumerateKeysAndObjectsUsingBlock:^(NSString *column, NSNumber *maxY, BOOL *stop) {

        if ([maxY floatValue] > [self.columnMaxY[maxColumn] floatValue])

        {

            maxColumn = column;

        }

    }];

    return CGSizeMake(0, [self.columnMaxY[maxColumn]floatValue]);

}

//允许每一次重新布局

-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds

{

    return YES;

}

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

    UICollectionViewLayoutAttributes * attLayout = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

    // 取出Y值最小的列

    NSString * minYColumKey = @"0";

    for(NSString * columKey in [[self columnMaxY] allKeys]){

        CGFloat maxY = [[[self columnMaxY] objectForKey:columKey] doubleValue];

        if([[[self columnMaxY] objectForKey:minYColumKey] doubleValue] > maxY){

            minYColumKey = columKey;

        }

    }

    CGSize itemSize = [self itemSizeWithIndexPath:indexPath];

    UIEdgeInsets edgeInsets = [self edgeInsetsWithIndexPath:indexPath];

    CGFloat columnSpacing   = [self columnSpacingWithIndexPath:indexPath];

    CGFloat lineSpacing     = [self lineSpacingWithIndexPath:indexPath];

    

    CGFloat x = edgeInsets.left+(itemSize.width+columnSpacing)*[minYColumKey intValue];

    CGFloat y = [[[self columnMaxY] objectForKey:minYColumKey] doubleValue];

    [[self columnMaxY] setValue:@(y+lineSpacing+itemSize.height) forKey:minYColumKey];

    CGRect newFrame = CGRectMake(x, y, itemSize.width, itemSize.height);

    [attLayout setFrame:newFrame];

    return attLayout;

}

-(NSMutableArray<UICollectionViewLayoutAttributes *> *)attrsArray{

    if(!_attrsArray){

        _attrsArray = [NSMutableArray array];

    }

    return _attrsArray;

}

- (NSMutableDictionary *)columnMaxY{

    if(!_columnMaxY){

        _columnMaxY = [NSMutableDictionary dictionary];

    }

    return _columnMaxY;

}

- (CGFloat)columnCountWithIndexPath:(NSIndexPath*)indexPath

{

    if([self delegate] && [[self delegate] respondsToSelector:@selector(collectionView:layout:columnCountForSectionAtIndex:)]){

        return [[self delegate] collectionView:[self collectionView] layout:self columnCountForSectionAtIndex:indexPath.section];

    }else{

        

        return ZJDefaultColumnCount;

    }

}

- (CGFloat)lineSpacingWithIndexPath:(NSIndexPath*)indexPath

{

    if([self delegate] && [[self delegate] respondsToSelector:@selector(collectionView:layout:lineSpacingForSectionAtIndex:)]){

        return [[self delegate] collectionView:[self collectionView] layout:self lineSpacingForSectionAtIndex:indexPath.section];

    }else{

        return ZJDefaultlineMargin;

    }

}

- (CGFloat)columnSpacingWithIndexPath:(NSIndexPath*)indexPath

{

    if([self delegate] && [[self delegate] respondsToSelector:@selector(collectionView:layout:columnSpacingForSectionAtIndex:)])

    {

        return [[self delegate] collectionView:[self collectionView] layout:self columnSpacingForSectionAtIndex:indexPath.section];

    }else{

        

        return ZJDefaultColumnMargin;

    }

}

- (UIEdgeInsets)edgeInsetsWithIndexPath:(NSIndexPath*)indexPath

{

    if([self delegate] && [[self delegate] respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)]){

        return [[self delegate] collectionView:[self collectionView] layout:self insetForSectionAtIndex:indexPath.section];

    }else{

        

        return ZJDefaultInsets;

    }

}

-(CGSize)itemSizeWithIndexPath:(NSIndexPath*)indexPath{

    if([self delegate] && [[self delegate] respondsToSelector:@selector(collectionView:layout:sizeForItemAtIndexPath:)]){

        return [[self delegate] collectionView:[self collectionView] layout:self sizeForItemAtIndexPath:indexPath];

    }else{

        CGFloat width = CGRectGetWidth([[self collectionView] frame]);

        

        UIEdgeInsets edgeInsets = [self edgeInsetsWithIndexPath:indexPath];

        CGFloat columnSpacing   = [self columnSpacingWithIndexPath:indexPath];

        NSInteger columnCount   = [self columnCountWithIndexPath:indexPath];

        CGFloat cellW = (width - edgeInsets.left - edgeInsets.right -

                         columnSpacing * (columnCount - 1)) / columnCount;

        return CGSizeMake(cellW, cellW);

    }

}

@end

猜你喜欢

转载自blog.csdn.net/qq_37191821/article/details/85264252