用factory模式解决瀑布流中展示不同风格的item

由于项目的需求,最近做了一个可以定义item不同的高度,并且可以显示不同item的瀑布流,拿出来供大家参考。

 

#import <UIKit/UIKit.h>

typedef  CGFloat(^itemHeightBlock)(NSIndexPath* index);

@interface WaterfallColectionLayout : UICollectionViewLayout

@property(nonatomic,strong )itemHeightBlock heightBlock ;

 

-(instancetype)initWithItemsHeightBlock:(itemHeightBlock)block;

@end

 

#import "WaterfallColectionLayout.h"

#define colMargin 5

#define colCount 4

#define rolMargin 5

@interface WaterfallColectionLayout ()

//数组存放每列的总高度

@property(nonatomic,strong)NSMutableArray* colsHeight;

//单元格宽度

@property(nonatomic,assign)CGFloat colWidth;

@end

 

@implementation WaterfallColectionLayout

-(instancetype)initWithItemsHeightBlock:(itemHeightBlock)block{

    if ([super init]) {

        self.heightBlock = block;

    }

    return self;

}

-(void)prepareLayout{

    [super prepareLayout];

    self.colWidth =( self.collectionView.frame.size.width - (colCount+1)*colMargin )/colCount;

    self.colsHeight = nil;

}

-(CGSize)collectionViewContentSize{

    NSNumber * longest = self.colsHeight[0];

    for (NSInteger i =0;i<self.colsHeight.count;i++) {

        NSNumber* rolHeight = self.colsHeight[i];

        if(longest.floatValue<rolHeight.floatValue){

            longest = rolHeight;

        }

    }

    return CGSizeMake(self.collectionView.frame.size.width, longest.floatValue);

}

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

    UICollectionViewLayoutAttributes* attr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

    NSNumber * shortest = self.colsHeight[0];

    NSInteger  shortCol = 0;

    for (NSInteger i =0;i<self.colsHeight.count;i++) {

        NSNumber* rolHeight = self.colsHeight[i];

        if(shortest.floatValue>rolHeight.floatValue){

            shortest = rolHeight;

            shortCol=i;

        }

    }

    CGFloat x = (shortCol+1)*colMargin+ shortCol * self.colWidth;

    CGFloat y = shortest.floatValue+colMargin;

    

    //获取cell高度

    CGFloat height=0;

    NSAssert(self.heightBlock!=nil, @"未实现计算高度的block ");

    if(self.heightBlock){

        height = self.heightBlock(indexPath);

    }

    attr.frame= CGRectMake(x, y, self.colWidth, height);

    self.colsHeight[shortCol]=@(shortest.floatValue+colMargin+height);

   

    return attr;

}

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

    NSMutableArray* array = [NSMutableArray array];

    NSInteger items = [self.collectionView numberOfItemsInSection:0];

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

        UICollectionViewLayoutAttributes* attr = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];

        [array addObject:attr];

    }

    return array;

}

-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{

    return YES;

}

-(NSMutableArray *)colsHeight{

    if(!_colsHeight){

        NSMutableArray * array = [NSMutableArray array];

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

            //这里可以设置初始高度

            [array addObject:@(0)];

        }

        _colsHeight = [array mutableCopy];

    }

    return _colsHeight;

}

@end

奉上demo地址:https://github.com/cocofcw/WaterfallCollectionLayout-master

posted @ 2017-03-31 13:31  fuchaowen  阅读(217)  评论(0编辑  收藏  举报