UICollectionView 再 见

来源:互联网 发布:unity3d 画虚线 编辑:程序博客网 时间:2024/06/10 00:12

第一次认识这个东西,感觉就是tableView的同父异母兄弟,慢慢的接触以及使用的时候,只是简单的流水布局,以及代理各种代理方法的使用。

譬如:


这样简单的使用其实没有感觉很low,因为需求简单,没有太复杂的UI所以就没有更深入的去了解过一些更“华丽的”东西。

获取当你看到这几个需求的时候就会想要深入的了解一些collectionView的布局问题了吧?

1.瀑布流式布局:


2.圆形布局:


3.方形布局:


4.常见的流水布局:

前面说到,常见流水布局,我们可以进去看一下.h里面的头文件,看看属性和方法:


那么就是说这个只是苹果帮我们封装好了一个流水布局而已,看继承关系就可以知道,他的父类就是UICollectionViewLayout。那么问题就来了,实现瀑布流,环形,方块形布局,我们亦可以自定义UICollectionViewLayout即可。

同理:

    我们可以类似布局瀑布流的效果:

  创建一个布局类,继承UICollectionViewLayout,然后在头文件里面创建协议,以及属性:


然后在实现文件里面进行各种实现:

首先是 默认值的设置:


然后是懒加载方式检测代理方法是否实现:

#pragma mark - 代理数据处理
/**
 *  行间距
 */
- (CGFloat)rowMargin
{
    if ([self.delegate respondsToSelector:@selector(rowMarginInWaterflowLayout:)]) {
        return [self.delegate rowMarginInWaterflowLayout:self];
    } else {
        return ZHZDefaultRowMargin;
    }
}
/**
 *  列间距
 */
- (CGFloat)columnMargin
{
    if ([self.delegate respondsToSelector:@selector(columnMarginInWaterflowLayout:)]) {
        return [self.delegate columnMarginInWaterflowLayout:self];
    } else {
        return ZHZDefaultColumnMargin;
    }
}
/**
 *  列数
 */
- (NSInteger)columnCount
{
    if ([self.delegate respondsToSelector:@selector(columnCountInWaterflowLayout:)]) {
        return [self.delegate columnCountInWaterflowLayout:self];
    } else {
        return ZHZDefaultColumnCount;
    }
}
/**
 *  collectionView内边距
 */
- (UIEdgeInsets)edgeInsets
{
    if ([self.delegate respondsToSelector:@selector(edgeInsetsInWaterflowLayout:)]) {
        return [self.delegate edgeInsetsInWaterflowLayout:self];
    } else {
        return ZHZDefaultEdgeInsets;
    }
}

- (NSMutableArray *)columnHeights
{
    if (!_columnHeights) {
        _columnHeights = [NSMutableArray array];
    }
    return _columnHeights;
}

- (NSMutableArray *)attrsArray
{
    if (!_attrsArray) {
        _attrsArray = [NSMutableArray array];
    }
    return _attrsArray;
}

然后就是实现方法了:


最后一步,实现布局:

/**
 * 返回indexPath位置cell对应的布局属性
 */
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
    // 创建布局属性
    UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    
    // collectionView的宽度
    CGFloat collectionViewW = self.collectionView.frame.size.width;
    
    // 设置布局属性的frame
    CGFloat Width = (collectionViewW - self.edgeInsets.left - self.edgeInsets.right - (self.columnCount - 1) * self.columnMargin) / self.columnCount;
    
    CGFloat Height = [self.delegate waterLayout:self itemWidth:Width indexPath:indexPath];
    
    // 找出高度最短的那一列
    NSInteger destColumn = 0;
    CGFloat minColumnHeight = [self.columnHeights[0] doubleValue];
    for (NSInteger i = 1; i < self.columnCount; i++) {
        // 取得第i列的高度
        CGFloat columnHeight = [self.columnHeights[i] doubleValue];
        
        if (minColumnHeight > columnHeight) {
            minColumnHeight = columnHeight;
            destColumn = i;
        }
    }
    
    CGFloat X = self.edgeInsets.left + destColumn * (Width + self.columnMargin);
    CGFloat Y = minColumnHeight;
    if (Y != self.edgeInsets.top) {
        Y += self.rowMargin;
    }
    attrs.frame = CGRectMake(X, Y, Width, Height);
    
    // 更新最短那列的高度(然后调此方法会重新计算)
    self.columnHeights[destColumn] = @(CGRectGetMaxY(attrs.frame));
    
    // 记录内容的高度
    CGFloat columnHeight = [self.columnHeights[destColumn] doubleValue];
    if (self.contentHeight < columnHeight) {
        self.contentHeight = columnHeight;
    }
    return attrs;
}
那么瀑布流就出来了,环形和方形呢???

只能同理了,所有布局的子类,大概最大的区别就是布局的实现即布局属性的返回方法:

环形:


方形:


最后贴一张UICollectionViewLayoutAttributes(布局属性的属性图)



0 0