美文网首页
UICollectionView 瀑布流实现

UICollectionView 瀑布流实现

作者: 空山和新雨 | 来源:发表于2018-03-22 08:30 被阅读0次

先讲一下思路。
如果要用UIScrollView实现瀑布流效果应该怎么做呢?

  1. 第一步当然是把UIScrollView初始化并放到目标View上
    2.你需要知道 要放多少个子view 到UIScrollView上
    3.你需要知道 每个子view的frame
    4.根据这些frame 计算出ScrollView的contentSize

That's all! 是不是很简单

UICollectionview的布局是由专门的类UICollectionViewLayout 来实现,我们通用的UICollectionViewFlowLayout无法实现瀑布流效果。 要简单实现瀑布流效果,只需要自定义一个继承与UICollectionViewLayout的子类, 并实现几个重要的方法(这里并不按调用顺序来讲)

1.- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
UICollectionViewLayoutAttributes是布局属性,这里包含了你需要的所有布局信息
根据每个cell的indexPath生成对应的布局属性对象,在这里这个cell的位置信息存放到attribute里 将并返回给UICollectionView
注意生成UICollectionViewLayoutAttributes 不能用alloc init方法创建, 而应该用[UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath] 获得, 否则会闪退
2、 - (void)prepareLayout
该方法会在UICollectionView呈现 刷新 或改变时调用
可以在里边实现一些初始化的操作, 遍历1方法,将获得的每个cell的attribute保存到一个特定数组attributeList里
3.- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
返回这个属性数组 attributeList

4.- (CGSize)collectionViewContentSize
返回整个页面的contentSize, 可以根据上面的attributeList算出

上代码

- (void)prepareLayout
{
    [super prepareLayout];
    [self.frameList removeAllObjects];
    [self.attrList removeAllObjects];
    for (NSMutableArray *arr in self.fList) {
        [arr removeAllObjects];
    }
    NSInteger count = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:0];
    for (int index = 0; index < count; index++) {
        UICollectionViewLayoutAttributes *attr = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]];
        NSValue *frameValue = [NSValue valueWithCGRect:attr.frame];
        CGFloat y = CGRectGetMinY(frameValue.CGRectValue);
        NSInteger i = (y - 10) / (h + 10);
        [self.frameList addObject:frameValue];
        [self.attrList addObject:attr];
    }
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewLayoutAttributes *attr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    
    NSInteger index = indexPath.item;
    NSInteger i = index % colume;
    NSInteger j = index / colume;
    CGFloat y, w;
    __block CGFloat x;
    if (index < colume) {
        y = 10 + i * (h + 10);
    } else {
        NSValue *f1 = [self.fList[0] lastObject];
        NSValue *f2 = [self.fList[1] lastObject];
        NSValue *f3 = [self.fList[2] lastObject];
        CGFloat x1 = CGRectGetMaxX([f1 CGRectValue]);
        CGFloat x2 = CGRectGetMaxX([f2 CGRectValue]);
        CGFloat x3 = CGRectGetMaxX([f3 CGRectValue]);
        if (x1 <= x2 && x1 <= x3) {
            y = CGRectGetMinY([f1 CGRectValue]);
            i = 0;
        } else if (x2 <= x1 && x2 <= x3) {
            y = CGRectGetMinY([f2 CGRectValue]);
            i = 1;
        } else {
            y = CGRectGetMinY([f3 CGRectValue]);
            i = 2;
        }
    }
    //    x = 10 + i * (w + 10);
    w = arc4random() % 200 + 50;
    x = 10;
    if (j == 0) {
        
    } else {
        [self.fList[i] enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            CGFloat ch = CGRectGetWidth([(NSValue *)obj CGRectValue]);
            x += ch + 10;
        }];
    }
    attr.frame = CGRectMake(x, y, w, h);
    NSLog(@"index = %ld x = %lf, y = %lf, w = %lf, h = %lf", index, x, y, w, h);
    return attr;
}

- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
    return self.attrList;
}

- (CGSize)collectionViewContentSize {
    CGRect lastFrame = [(NSValue *)[self.frameList lastObject] CGRectValue];
    return CGSizeMake(CGRectGetMaxX(lastFrame), 0);
}

相关文章

网友评论

      本文标题:UICollectionView 瀑布流实现

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