美文网首页
iOS UICollectionView之瀑布流

iOS UICollectionView之瀑布流

作者: 点滴86 | 来源:发表于2018-10-20 14:46 被阅读76次

    瀑布流的实现
    实现一个自定义的瀑布流UICollectionViewLayout的常规做法是继承UICollectionViewLayout,然后重载下列方法

    // 布局计算
    -(void)prepareLayout
    
    // 返回collectionView的内容尺寸
    -(CGSize)collectionViewContentSize
    
    /**
     *  返回rect中的所有元素的布局属性
     *  返回的是包含UICollectionViewLayoutAttributes的数组
     *  UICollectionViewLayoutAttributes可以是cell、SupplementaryView或者DecorationView的信息通过不同的UICollectionViewLayoutAttributes初始化方法可以得到不同类型的UICollectionViewLayoutAttributes
     *  + (instancetype)layoutAttributesForCellWithIndexPath:(NSIndexPath *)indexPath
     *  + (instancetype)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind withIndexPath:(NSIndexPath *)indexPath
     *  + (instancetype)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind withIndexPath:(NSIndexPath *)indexPath
     */
    -(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
    
    // 返回对应于indexPath的位置的cell的布局属性
    - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)path
    
    // 返回对应于indexPath位置的SupplementaryView的布局属性,如果没有SupplementaryView可不重载
    - (nullable UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath;
    
    //  返回对应于indexPath位置的DecorationView的布局属性,如果没有DecorationView可不重载
    - (nullable UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString*)elementKind atIndexPath:(NSIndexPath *)indexPath;
    

    DMWaterfallFlowLayout.h

    #import <UIKit/UIKit.h>
    
    @class DMWaterfallFlowLayout;
    
    @protocol DMWaterfallFlowLayoutDelegate <NSObject>
    
    @required
    /**
     *  cell 高度
     */
    - (CGFloat)waterfallFlowLayout:(DMWaterfallFlowLayout *)waterfallFlowLayout heightForItemAtIndexPath:(NSIndexPath *)indexPath itemWidth:(CGFloat)width;
    
    @optional
    /**
     * 分区 sectionHeader 高度
     */
    - (CGFloat)waterfallFlowLayout:(DMWaterfallFlowLayout *)waterfallFlowLayout heightForHeaderInSection:(NSInteger)section;
    
    /**
     * 分区 sectionFooter 高度
     */
    - (CGFloat)waterfallFlowLayout:(DMWaterfallFlowLayout *)waterfallFlowLayout heightForFooterInSection:(NSInteger)section;
    
    /**
     *  分区 列数
     */
    - (NSInteger)waterfallFlowLayout:(DMWaterfallFlowLayout *)waterfallFlowLayout columnCountInSection:(NSInteger)section;
    
    /**
     *  分区 列间距
     */
    - (CGFloat)waterfallFlowLayout:(DMWaterfallFlowLayout *)waterfallFlowLayout columnMarginInSection:(NSInteger)section;
    
    /**
     *  分区 行间距
     */
    - (CGFloat)waterfallFlowLayout:(DMWaterfallFlowLayout *)waterfallFlowLayout rowMarginInSection:(NSInteger)section;
    
    /**
     *  分区 UIEdgeInsets
     */
    - (UIEdgeInsets)waterfallFlowLayout:(DMWaterfallFlowLayout *)waterfallFlowLayout edgeInsetsInSection:(NSInteger)section;
    
    @end
    
    @interface DMWaterfallFlowLayout : UICollectionViewFlowLayout
    
    @property (nonatomic, weak) id<DMWaterfallFlowLayoutDelegate> delegate;
    
    - (CGFloat)headerHeightInSection:(NSInteger)section;
    
    - (CGFloat)footerHeightInSection:(NSInteger)section;
    
    - (NSInteger)columnCountInSection:(NSInteger)section;
    
    - (CGFloat)columnMarginInSection:(NSInteger)section;
    
    - (CGFloat)rowMarginInSection:(NSInteger)section;
    
    - (UIEdgeInsets)edgeInsetsInSection:(NSInteger)section;
    
    @end
    

    DMWaterfallFlowLayout.m

    #import "DMWaterfallFlowLayout.h"
    
    /** section Header 高度 */
    static const CGFloat DMDefaultHeaderHeight = 0;
    
    /** section Footer 高度 */
    static const CGFloat DMDefaultFooterHeight = 0;
    
    /** 列数 */
    static const NSInteger DMDefaultColumCount = 2;
    
    /** 每一列间距 */
    static const CGFloat DMDefaultColumMargin = 10;
    
    /** 每一行间距 */
    static const CGFloat DMDefaultRowMargin = 10;
    
    /** 边缘间距 */
    static const UIEdgeInsets DMDefaultEdgeInsets = {10,0,10,0};
    
    
    @interface DMWaterfallFlowLayout ()
    
    /** 布局属性数组 */
    @property (nonatomic, strong) NSMutableArray *attrsArray;
    
    /** 存放section数组,每一个section数组中存放列的当前高度 */
    @property (nonatomic, strong) NSMutableArray *columnHeightArray;
    
    @end
    
    @implementation DMWaterfallFlowLayout
    
    #pragma mark - life cycle
    - (void)prepareLayout
    {
        [super prepareLayout];
        
        //如果刷新布局就会重新调用prepareLayout这个方法,所以要先把高度数组清空
        [self.columnHeightArray removeAllObjects];
        [self.attrsArray removeAllObjects];
        
        NSInteger sectionNum = [self.collectionView numberOfSections];
        for (NSInteger sectionIndex = 0; sectionIndex < sectionNum; sectionIndex++) {
            // 获取前一个section的高度
            CGFloat tmpBottom = 0;
            if (sectionIndex != 0) {
                NSArray *beforeColumnHeightArray = [self.columnHeightArray objectAtIndex:sectionIndex - 1];
                for (NSNumber *curNum in beforeColumnHeightArray) {
                    if (tmpBottom < [curNum floatValue]) {
                        tmpBottom = [curNum floatValue];
                    }
                }
            }
            
            // 1.先判断是否存在section Header
            CGFloat headerHeight = [self headerHeightInSection:sectionIndex];
            if (headerHeight > 0) {
                //获取UICollectionElementKindSectionHeader对应的布局属性
                NSIndexPath *curIndexPath = [NSIndexPath indexPathForRow:0 inSection:sectionIndex];
                UICollectionViewLayoutAttributes *layoutHeader = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:curIndexPath];
                [self.attrsArray addObject:layoutHeader];
            }
            
            // section edge inset
            UIEdgeInsets sectionEdgeInsets = [self edgeInsetsInSection:sectionIndex];
            
            // cell
            NSInteger tmpColumnCount = [self columnCountInSection:sectionIndex];
            NSMutableArray *tmpColumnHeightArray = [[NSMutableArray alloc] init];
            for (NSInteger columnIndex = 0; columnIndex < tmpColumnCount; columnIndex++) {
                [tmpColumnHeightArray addObject:[NSNumber numberWithFloat:tmpBottom + headerHeight + sectionEdgeInsets.top]];
            }
            
            [self.columnHeightArray addObject:tmpColumnHeightArray];
            NSInteger itemsNum = [self.collectionView numberOfItemsInSection:sectionIndex];
            for (NSInteger itemIndex = 0; itemIndex < itemsNum; itemIndex++) {
                NSIndexPath *indexPath = [NSIndexPath indexPathForRow:itemIndex inSection:sectionIndex];
                //获取indexPath 对应cell 的布局属性
                UICollectionViewLayoutAttributes *attr = [self layoutAttributesForItemAtIndexPath:indexPath];
                [self.attrsArray addObject:attr];
            }
            
            if (sectionEdgeInsets.bottom > 0) {
                for (NSInteger columnIndex = 0; columnIndex < tmpColumnCount; columnIndex++) {
                    // 更新数组中列的当前高度
                    NSNumber *curHeight = tmpColumnHeightArray[columnIndex];
                    tmpColumnHeightArray[columnIndex] = [NSNumber numberWithFloat:curHeight.doubleValue + sectionEdgeInsets.bottom];
                }
            }
            
            // section Footer
            CGFloat footerHeight = [self footerHeightInSection:sectionIndex];
            if (footerHeight > 0) {
                //获取UICollectionElementKindSectionFooter对应的布局属性
                NSIndexPath *curIndexPath = [NSIndexPath indexPathForRow:0 inSection:sectionIndex];
                UICollectionViewLayoutAttributes *layoutFooter = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter atIndexPath:curIndexPath];
                [self.attrsArray addObject:layoutFooter];
                for (NSInteger columnIndex = 0; columnIndex < tmpColumnCount; columnIndex++) {
                    // 更新数组中列的当前高度
                    NSNumber *curHeight = tmpColumnHeightArray[columnIndex];
                    tmpColumnHeightArray[columnIndex] = [NSNumber numberWithFloat:curHeight.doubleValue + footerHeight];
                }
            }
        }
    }
    
    /**
     *  返回supplementaryView对应的布局属性
     */
    - (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath
    {
        UICollectionViewLayoutAttributes *tempAttr = nil;
        if ([elementKind isEqualToString:UICollectionElementKindSectionHeader]) {
            UICollectionViewLayoutAttributes *attr = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:elementKind withIndexPath:indexPath];
            NSInteger sectionIndex = indexPath.section;
            CGFloat headerOriginY = 0;
            // 前一个section的高度
            if (sectionIndex != 0) {
                NSArray *beforeColumnHeightArray = [self.columnHeightArray objectAtIndex:sectionIndex - 1];
                for (NSNumber *curNum in beforeColumnHeightArray) {
                    if (headerOriginY < [curNum floatValue]) {
                        headerOriginY = [curNum floatValue];
                    }
                }
            }
            
            CGFloat headerHeight = [self headerHeightInSection:sectionIndex];
            // 设置frame
            attr.frame = CGRectMake(0, headerOriginY, [UIScreen mainScreen].bounds.size.width, headerHeight);
            tempAttr = attr;
        } else if ([elementKind isEqualToString:UICollectionElementKindSectionFooter]) {
            NSInteger sectionIndex = indexPath.section;
            CGFloat footerOriginY = 0;
            NSArray *curColumnHeightArray = [self.columnHeightArray objectAtIndex:sectionIndex];
            for (NSNumber *curNum in curColumnHeightArray) {
                if (footerOriginY < [curNum floatValue]) {
                    footerOriginY = [curNum floatValue];
                }
            }
            
            UICollectionViewLayoutAttributes *layoutFooter = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter withIndexPath:indexPath];
            CGFloat footerHeight = [self footerHeightInSection:sectionIndex];
            // 设置frame
            layoutFooter.frame = CGRectMake(0, footerOriginY, [UIScreen mainScreen].bounds.size.width, footerHeight);
            
            tempAttr = layoutFooter;
        }
        
        return tempAttr;
    }
    
    /**
     *  返回indexPath 位置cell对应的布局属性
     */
    - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        UICollectionViewLayoutAttributes *attr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
        
        NSInteger sectionIndex = indexPath.section;
        NSMutableArray *curColumnHeightArray =  [self.columnHeightArray objectAtIndex:sectionIndex];
        
        // 获取前一个section的高度
        CGFloat tmpBottom = 0;
        if (sectionIndex != 0) {
            NSArray *beforeColumnHeightArray = [self.columnHeightArray objectAtIndex:sectionIndex - 1];
            for (NSNumber *curNum in beforeColumnHeightArray) {
                if (tmpBottom < [curNum floatValue]) {
                    tmpBottom = [curNum floatValue];
                }
            }
        }
        
        // 当前section的section header
        CGFloat headerHeight = [self headerHeightInSection:sectionIndex];
        if (headerHeight > 0) {
            tmpBottom += headerHeight;
        }
        
        // section edge inset
        UIEdgeInsets sectionEdgeInsets = [self edgeInsetsInSection:sectionIndex];
        
        CGFloat sectionColumnMargin =  [self columnMarginInSection:sectionIndex];
        CGFloat sectionRowMargin =  [self rowMarginInSection:sectionIndex];
        
        //使用for循环,找出高度最短的那一列
        //最短高度的列(即存放当前cell的列)
        NSInteger destColumn = 0;
        CGFloat minColumnHeight = [curColumnHeightArray[0] doubleValue];
        
        NSInteger tmpColumnCount = [self columnCountInSection:sectionIndex];
        for (NSInteger i = 1; i < tmpColumnCount; i++) {
            CGFloat columnHeight  = [curColumnHeightArray[i] doubleValue];
            if (minColumnHeight > columnHeight) {
                minColumnHeight = columnHeight;
                destColumn = I;
            }
        }
        
        //cell item的宽度
        CGFloat w = (self.collectionView.frame.size.width - sectionEdgeInsets.left - sectionEdgeInsets.right - (tmpColumnCount - 1) * sectionColumnMargin ) / tmpColumnCount;
        //cell item的高度
        CGFloat h = [self.delegate waterfallFlowLayout:self heightForItemAtIndexPath:indexPath itemWidth:w];
        //cell item的起点x
        CGFloat x = sectionEdgeInsets.left + destColumn * (w + sectionColumnMargin);
        //cell item的起点y
        CGFloat y = minColumnHeight ;
        
        // 当前cell不是分区的第一行cell 时 添加一个行Margin
        if (y != tmpBottom + sectionEdgeInsets.top) {
            y += sectionRowMargin;
        }
        
        // 设置frame
        attr.frame = CGRectMake(x,y,w,h);
        
        // 修改数组中当前列的高度
        curColumnHeightArray[destColumn] =  [NSNumber numberWithFloat:y+ h];
        
        return attr;
    }
    
    /**
     *  决定UICollectionView的排布
     */
    - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
    {
        return self.attrsArray;
    }
    
    /**
     *  可滑动范围
     */
    - (CGSize)collectionViewContentSize
    {
        CGFloat maxHeight = 0;
        NSInteger sectionNum = [self.collectionView numberOfSections];
        
        if (sectionNum > 0) {
            NSArray *curColumnHeightArray = [self.columnHeightArray objectAtIndex:sectionNum - 1];
            for (NSNumber *curNum in curColumnHeightArray) {
                if (maxHeight < [curNum floatValue]) {
                    maxHeight = [curNum floatValue];
                }
            }
        }
        
        return CGSizeMake(0, maxHeight);
    }
    
    #pragma mark - public method
    - (CGFloat)headerHeightInSection:(NSInteger)section
    {
        CGFloat tempHeaderHeight = 0;
        if (self.delegate && [self.delegate respondsToSelector:@selector(waterfallFlowLayout:heightForHeaderInSection:)]) {
            tempHeaderHeight = [self.delegate waterfallFlowLayout:self heightForHeaderInSection:section];
        } else {
            tempHeaderHeight = DMDefaultHeaderHeight;
        }
        
        return tempHeaderHeight;
    }
    
    - (CGFloat)footerHeightInSection:(NSInteger)section
    {
        CGFloat tempHeaderHeight = 0;
        if (self.delegate && [self.delegate respondsToSelector:@selector(waterfallFlowLayout:heightForFooterInSection:)]) {
            tempHeaderHeight = [self.delegate waterfallFlowLayout:self heightForFooterInSection:section];
        } else {
            tempHeaderHeight = DMDefaultFooterHeight;
        }
        
        return tempHeaderHeight;
    }
    
    - (NSInteger)columnCountInSection:(NSInteger)section
    {
        NSInteger tempColumn = 0;
        if (self.delegate && [self.delegate respondsToSelector:@selector(waterfallFlowLayout:columnCountInSection:)]) {
            tempColumn = [self.delegate waterfallFlowLayout:self columnCountInSection:section];
        } else {
            tempColumn = DMDefaultColumCount;
        }
        
        return tempColumn;
    }
    
    - (CGFloat)columnMarginInSection:(NSInteger)section
    {
        CGFloat tempColumnMargin = 0;
        if (self.delegate && [self.delegate respondsToSelector:@selector(waterfallFlowLayout:columnMarginInSection:)]) {
            tempColumnMargin = [self.delegate waterfallFlowLayout:self columnMarginInSection:section];
        } else {
            tempColumnMargin = DMDefaultColumMargin;
        }
        
        return tempColumnMargin;
    }
    
    - (CGFloat)rowMarginInSection:(NSInteger)section
    {
        CGFloat tempRowMargin = 0;
        if (self.delegate && [self.delegate respondsToSelector:@selector(waterfallFlowLayout:rowMarginInSection:)]) {
            tempRowMargin = [self.delegate waterfallFlowLayout:self rowMarginInSection:section];
        } else {
            tempRowMargin = DMDefaultRowMargin;
        }
        
        return tempRowMargin;
    }
    
    - (UIEdgeInsets)edgeInsetsInSection:(NSInteger)section
    {
        UIEdgeInsets tempEdgeInset = UIEdgeInsetsZero;
        if (self.delegate && [self.delegate respondsToSelector:@selector(waterfallFlowLayout:edgeInsetsInSection:)]) {
            tempEdgeInset = [self.delegate waterfallFlowLayout:self edgeInsetsInSection:section];
        } else {
            tempEdgeInset = DMDefaultEdgeInsets;
        }
        
        return tempEdgeInset;
    }
    
    #pragma mark - getter and setter
    - (NSMutableArray *)attrsArray
    {
        if (_attrsArray == nil) {
            _attrsArray = [[NSMutableArray alloc] init];
        }
        
        return _attrsArray;
    }
    
    - (NSMutableArray *)columnHeightArray
    {
        if (_columnHeightArray == nil) {
            _columnHeightArray = [[NSMutableArray alloc] init];
        }
        
        return _columnHeightArray;
    }
    
    @end
    

    注释已经很详细了
    看一下如何使用,实例如下

    #import "DMFunctionWaterfallViewController.h"
    #import "DMWaterfallFlowLayout.h"
    #import "DMSectionHeaderCollectionReusableView.h"
    #import "DMSectionFooterCollectionReusableView.h"
    #import "DMNormalCollectionViewCell.h"
    #import "DMWaterfallCollectionViewCell.h"
    
    static NSString * const kDMSectionHeaderCollectionReusableViewIdentifier = @"kDMSectionHeaderCollectionReusableViewIdentifier";
    static NSString * const kDMSectionFooterCollectionReusableViewIdentifier = @"kDMSectionFooterCollectionReusableViewIdentifier";
    static NSString * const kDMNormalCollectionViewCellIdentifier = @"kDMNormalCollectionViewCellIdentifier";
    static NSString * const kDMWaterfallCollectionViewCellIdentifier = @"kDMWaterfallCollectionViewCellIdentifier";
    
    @interface DMFunctionWaterfallViewController () <UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, DMWaterfallFlowLayoutDelegate>
    
    /** UI */
    @property (nonatomic, strong) UICollectionView *myCollectionView;
    
    
    /** DATA */
    @property (nonatomic, strong) NSMutableArray *dataArray;
    
    @end
    
    @implementation DMFunctionWaterfallViewController
    
    #pragma mark - life cycle
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        self.view.backgroundColor = [UIColor whiteColor];
        self.title = @"瀑布流";
        [self initData];
        
        [self.view addSubview:self.myCollectionView];
    }
    
    - (void)initData
    {
        {
            NSMutableArray *sectionOneArray = [[NSMutableArray alloc] init];
            {
                DMNormalCollectionViewCellModel *modelOne = [[DMNormalCollectionViewCellModel alloc] init];
                modelOne.imageName = @"picOne";
                [sectionOneArray addObject:modelOne];
            }
            {
                DMNormalCollectionViewCellModel *modelTwo = [[DMNormalCollectionViewCellModel alloc] init];
                modelTwo.imageName = @"picTow";
                [sectionOneArray addObject:modelTwo];
            }
            [self.dataArray addObject:sectionOneArray];
        }
        
        {
            NSMutableArray *sectionTwoArray = [[NSMutableArray alloc] init];
            {
                DMWaterfallCollectionViewCellModel *modelOne = [[DMWaterfallCollectionViewCellModel alloc] init];
                modelOne.imageName = @"YY1";
                modelOne.ratioNum = [NSNumber numberWithFloat:1/1.5];
                modelOne.numStr = @"1";
                [sectionTwoArray addObject:modelOne];
            }
            {
                DMWaterfallCollectionViewCellModel *modelTwo = [[DMWaterfallCollectionViewCellModel alloc] init];
                modelTwo.imageName = @"YY2";
                modelTwo.ratioNum = [NSNumber numberWithFloat:1.5/1.0];
                modelTwo.numStr = @"2";
                [sectionTwoArray addObject:modelTwo];
            }
            {
                DMWaterfallCollectionViewCellModel *modelThree = [[DMWaterfallCollectionViewCellModel alloc] init];
                modelThree.imageName = @"YY3";
                modelThree.ratioNum = [NSNumber numberWithFloat:1/1.6];
                modelThree.numStr = @"3";
                [sectionTwoArray addObject:modelThree];
            }
            {
                DMWaterfallCollectionViewCellModel *modelFour = [[DMWaterfallCollectionViewCellModel alloc] init];
                modelFour.imageName = @"YY4";
                modelFour.ratioNum = [NSNumber numberWithFloat:1/1.7];
                modelFour.numStr = @"4";
                [sectionTwoArray addObject:modelFour];
            }
            {
                DMWaterfallCollectionViewCellModel *modelThree = [[DMWaterfallCollectionViewCellModel alloc] init];
                modelThree.imageName = @"YY5";
                modelThree.ratioNum = [NSNumber numberWithFloat:1/1.8];
                modelThree.numStr = @"5";
                [sectionTwoArray addObject:modelThree];
            } 
            [self.dataArray addObject:sectionTwoArray];
        }
        
        {
            NSMutableArray *sectionThreeArray = [[NSMutableArray alloc] init];
            {
                DMNormalCollectionViewCellModel *modelOne = [[DMNormalCollectionViewCellModel alloc] init];
                modelOne.imageName = @"mountain1";
                [sectionThreeArray addObject:modelOne];
            }
            {
                DMNormalCollectionViewCellModel *modelTwo = [[DMNormalCollectionViewCellModel alloc] init];
                modelTwo.imageName = @"mountain2";
                [sectionThreeArray addObject:modelTwo];
            }
            {
                DMNormalCollectionViewCellModel *modelThree = [[DMNormalCollectionViewCellModel alloc] init];
                modelThree.imageName = @"mountain3";
                [sectionThreeArray addObject:modelThree];
            }
            {
                DMNormalCollectionViewCellModel *modelFour = [[DMNormalCollectionViewCellModel alloc] init];
                modelFour.imageName = @"mountain4";
                [sectionThreeArray addObject:modelFour];
            }
            [self.dataArray addObject:sectionThreeArray];
        }
    }
    
    #pragma mark - UICollectionViewDataSource method
    - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
    {
        NSInteger sectionNum = 0;
        sectionNum = [self.dataArray count];
        
        return sectionNum;
    }
    
    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
    {
        NSInteger itemsNum = 0;
        NSArray *itemsArray = [self.dataArray objectAtIndex:section];
        itemsNum = [itemsArray count];
        
        return itemsNum;
    }
    
    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        UICollectionViewCell *cell = nil;
        NSInteger sectionIndex = indexPath.section;
        NSInteger rowIndex = indexPath.row;
        NSArray *tmpDataArray = [self.dataArray objectAtIndex:sectionIndex];
        if (sectionIndex == 0) {
            DMNormalCollectionViewCell * tmpCell = [collectionView dequeueReusableCellWithReuseIdentifier:kDMNormalCollectionViewCellIdentifier forIndexPath:indexPath];
            DMNormalCollectionViewCellModel *dataModel = [tmpDataArray objectAtIndex:rowIndex];
            [tmpCell setDataModel:dataModel];
            cell = tmpCell;
        } else if (sectionIndex == 1) {
            DMWaterfallCollectionViewCell *tmpCell = [collectionView dequeueReusableCellWithReuseIdentifier:kDMWaterfallCollectionViewCellIdentifier forIndexPath:indexPath];
            DMWaterfallCollectionViewCellModel *dataModel = [tmpDataArray objectAtIndex:rowIndex];
            [tmpCell setDataModel:dataModel];
            cell = tmpCell;
        } else {
            DMNormalCollectionViewCell * tmpCell = [collectionView dequeueReusableCellWithReuseIdentifier:kDMNormalCollectionViewCellIdentifier forIndexPath:indexPath];
            DMNormalCollectionViewCellModel *dataModel = [tmpDataArray objectAtIndex:rowIndex];
            [tmpCell setDataModel:dataModel];
            cell = tmpCell;
        }
        
        return cell;
    }
    
    - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
    {
        UICollectionReusableView *tmpView = nil;
        NSInteger sectionIndex = indexPath.section;
        if (sectionIndex == 0) {
            if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
                DMSectionHeaderCollectionReusableView *headerView =  [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:kDMSectionHeaderCollectionReusableViewIdentifier forIndexPath:indexPath];
                [headerView updateStr:@"第一个分区头部"];
                headerView.backgroundColor = [UIColor redColor];
                tmpView = headerView;
            } else if ([kind isEqualToString:UICollectionElementKindSectionFooter]) {
                DMSectionHeaderCollectionReusableView *footerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:kDMSectionFooterCollectionReusableViewIdentifier forIndexPath:indexPath];
                [footerView updateStr:@"第一个分区尾部"];
                footerView.backgroundColor = [UIColor yellowColor];
                tmpView = footerView;
            }
        } else if (sectionIndex == 1) {
            if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
                DMSectionHeaderCollectionReusableView *headerView =  [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:kDMSectionHeaderCollectionReusableViewIdentifier forIndexPath:indexPath];
                [headerView updateStr:@"第二个分区头部"];
                headerView.backgroundColor = [UIColor greenColor];
                tmpView = headerView;
            } else if ([kind isEqualToString:UICollectionElementKindSectionFooter]) {
                DMSectionHeaderCollectionReusableView *footerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:kDMSectionFooterCollectionReusableViewIdentifier forIndexPath:indexPath];
                [footerView updateStr:@"第二个分区尾部"];
                footerView.backgroundColor = [UIColor purpleColor];
                tmpView = footerView;
            }
        }
        
        return tmpView;
    }
    
    #pragma mark - UICollectionViewDelegate method
    
    #pragma mark - DMWaterfallFlowLayoutDelegate method
    - (CGFloat)waterfallFlowLayout:(DMWaterfallFlowLayout *)waterfallFlowLayout heightForItemAtIndexPath:(NSIndexPath *)indexPath itemWidth:(CGFloat)width
    {
        NSInteger sectionIndex = indexPath.section;
        CGFloat itemHeight = 0;
        if (sectionIndex == 0) {
            itemHeight = [DMNormalCollectionViewCell cellHeight];
        } else if (sectionIndex == 1) {
            NSInteger sectionIndex = indexPath.section;
            NSInteger rowIndex = indexPath.row;
            NSArray *tmpDataArray = [self.dataArray objectAtIndex:sectionIndex];
            DMWaterfallCollectionViewCellModel *dataModel = [tmpDataArray objectAtIndex:rowIndex];
            itemHeight = width / [dataModel.ratioNum floatValue];
        } else if (sectionIndex == 2) {
            itemHeight = [DMNormalCollectionViewCell cellHeight];
        }
        
        return itemHeight;
    }
    
    /**
     * sectionHeader 高度
     */
    - (CGFloat)waterfallFlowLayout:(DMWaterfallFlowLayout *)waterfallFlowLayout heightForHeaderInSection:(NSInteger)section
    {
        CGFloat headerHeight = 0;
        if (section == 0) {
            headerHeight = 60;
        } else if (section == 1) {
            headerHeight = 40;
        }
        
        return headerHeight;
    }
    
    /**
     * sectionFooter 高度
     */
    - (CGFloat)waterfallFlowLayout:(DMWaterfallFlowLayout *)waterfallFlowLayout heightForFooterInSection:(NSInteger)section
    {
        CGFloat footerHeight = 0;
        if (section == 0) {
            footerHeight = 50;
        } else if (section == 1) {
            footerHeight = 40;
        }
        
        return footerHeight;
    }
    
    /**
     *  列数
     */
    - (NSInteger)waterfallFlowLayout:(DMWaterfallFlowLayout *)waterfallFlowLayout columnCountInSection:(NSInteger)section
    {
        NSInteger columnCount = 0;
        if (section == 0) {
            columnCount = 1;
        } else if (section == 1) {
            columnCount = 2;
        } else {
            columnCount = 1;
        }
        
        return columnCount;
    }
    
    /**
     *  列间距
     */
    - (CGFloat)waterfallFlowLayout:(DMWaterfallFlowLayout *)waterfallFlowLayout columnMarginInSection:(NSInteger)section
    {
        CGFloat columnMargin = 0;
        if (section == 1) {
            columnMargin = 15;
        }
        
        return columnMargin;
    }
    
    /**
     *  行间距
     */
    - (CGFloat)waterfallFlowLayout:(DMWaterfallFlowLayout *)waterfallFlowLayout rowMarginInSection:(NSInteger)section
    {
        CGFloat rowMargin = 0;
        if (section == 0) {
            rowMargin = 10;
        } else if (section == 1) {
            rowMargin = 15;
        } else {
            rowMargin = 10;
        }
        
        return rowMargin;
    }
    
    /**
     *  UIEdgeInsets
     */
    - (UIEdgeInsets)waterfallFlowLayout:(DMWaterfallFlowLayout *)waterfallFlowLayout edgeInsetsInSection:(NSInteger)section
    {
        UIEdgeInsets sectionEdgeInsets = UIEdgeInsetsZero;
        if (section == 0) {
            sectionEdgeInsets = UIEdgeInsetsMake(10, 0, 10, 0);
        } else if (section == 1) {
            sectionEdgeInsets = UIEdgeInsetsMake(15, 15, 15, 15);
        } else {
           sectionEdgeInsets = UIEdgeInsetsMake(10, 0, 10, 0);
        }
        
        return sectionEdgeInsets;
    }
    
    #pragma mark - getter and setter
    - (UICollectionView *)myCollectionView
    {
        if (_myCollectionView == nil) {
            DMWaterfallFlowLayout *waterfallFlowLayout = [[DMWaterfallFlowLayout alloc] init];
            waterfallFlowLayout.delegate = self;
            _myCollectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 64, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 64) collectionViewLayout:waterfallFlowLayout];
            _myCollectionView.dataSource = self;
            _myCollectionView.backgroundColor = [UIColor whiteColor];
            _myCollectionView.delegate = self;
            [_myCollectionView registerClass:[DMSectionHeaderCollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:kDMSectionHeaderCollectionReusableViewIdentifier];
            [_myCollectionView registerClass:[DMSectionFooterCollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:kDMSectionFooterCollectionReusableViewIdentifier];
            [_myCollectionView registerClass:[DMNormalCollectionViewCell class] forCellWithReuseIdentifier:kDMNormalCollectionViewCellIdentifier];
            [_myCollectionView registerClass:[DMWaterfallCollectionViewCell class] forCellWithReuseIdentifier:kDMWaterfallCollectionViewCellIdentifier];
        }
        
        return _myCollectionView;
    }
    
    - (NSMutableArray *)dataArray
    {
        if (_dataArray == nil) {
            _dataArray = [[NSMutableArray alloc] init];
        }
        
        return _dataArray;
    }
    

    效果图如下


    瀑布流-1.gif

    瀑布流部分是第二个section,第一个section和第三个section是正常的。

    相关文章

      网友评论

          本文标题:iOS UICollectionView之瀑布流

          本文链接:https://www.haomeiwen.com/subject/jueuzftx.html