【iOS】瀑布流的实现

1、效果演示

Simulator Screen Shot - iPhone 8 - 2020-01-16 at 17.32.16.png

2、实现思路

根据瀑布流的列数,创建记录maxY的字典,例如两列的瀑布流,就创建两个Key去记录左右两列当前最大的maxY

// 初始化字典,有几列就有几个键值对,key为列,value为列的最大y值,
// 初始值为上内边距
for (int i = 0; i < self.column; i++) {
     self.maxYDic[@(i)] = @(self.sectionInset.top);
}

根据设置的列数,列间隙,以及左右inset,确定itemWidth

- (CGFloat)itemWidth
{
    CGFloat collectionViewWidth = self.collectionView.frame.size.width;
    if (collectionViewWidth == 0) {
        collectionViewWidth = [UIScreen mainScreen].bounds.size.width;
    }
    CGFloat itemWidth = (collectionViewWidth - self.sectionInset.left - self.sectionInset.right - (self.column) * self.columnSpacing * (self.column - 1)) / self.column;
    return itemWidth;
}

itemHeight从数据源获取

CGFloat itemHeight = [self.dataSource waterFallLayout:self itemHeightForItemWidth:itemWidth atIndexPath:attributes.indexPath];

判断最小的maxY在左列,还是右列,确定itemY和itemX,从而确定item的frame

/// 找出最短的一列
    __block NSNumber *minIndex = @(0);
    [self.maxYDic enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, NSNumber *obj, BOOL * _Nonnull stop) {
        if ([self.maxYDic[minIndex] floatValue] > [obj floatValue]) {
            minIndex = key;
        }
    }];
    // 根据最短列去计算itemX
    CGFloat itemX = self.sectionInset.left + (self.columnSpacing + itemWidth) * minIndex.intValue;
    CGFloat itemY = 0;
    if (self.column == 1) {
        // 一列情况
        if (indexPath.row == 0 ) {
            itemY = [self.maxYDic[minIndex] floatValue];
        }else{
            itemY = [self.maxYDic[minIndex] floatValue] + self.rowSpacing;
        }
    }else{
        // 瀑布流多列情况
        // 第一行Cell不需要添加RowSpacing, 对应的indexPath.row = 0 && =1;
        if (indexPath.row == 0 || indexPath.row == 1) {
            itemY = [self.maxYDic[minIndex] floatValue];
        }else{
            itemY = [self.maxYDic[minIndex] floatValue] + self.rowSpacing;
        }
    }
    attributes.frame = CGRectMake(itemX, itemY , itemWidth, itemHeight);

以上就是核心代码和思路,具体代码请下载源码

3、需要重写的方法

继承UICollectionViewLayout重写以下方法

/// 1、初始化数据源
- (void)prepareLayout
/// 2、计算每个Attribute
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
/// 3、返回数据源
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
/// 4、返回itemSize
- (CGSize)collectionViewContentSize

4、下载地址

https://github.com/maple1994/MPPlayerDemo

推荐阅读更多精彩内容

  • 三种方法实现 一、scrollView做垫子,上面添加多个tableView(不可取); 效率低下,cell不能循...
    SadMine阅读 329评论 0 0
  • 背景 近期公司启动了Pad项目,项目中大部分的功能实现都是基于CollectionView实现的,并且cell的高...
    小码农_gjw阅读 1,425评论 0 1
  • 为何我会对瀑布流为这么上进,非要将瀑布流来一次大清洗,非逼得自己将它彻底弄清楚。原因其实也很简单:之前刚出来找工作...
    smooth_lgh阅读 3,821评论 1 5
  • 最近一直在做项目,没什么时间发博客.现在有空了,整理一下这段时间项目里的一些实用技术.如果有问题欢迎随时找我交流....
    Go_Spec阅读 2,436评论 8 34
  • 上集地址www.jianshu.com/p/9ed8547a9fd6 重生 一 文集山东去三四十里有一座小小的庄院...
    夕花朝颜阅读 265评论 0 0