iOS开发之UICollectionView(二)

本文主要介绍自定义UICollectionView布局类UICollectionViewLayout,实现简单瀑布流视图。

利用自定义UICollectionViewLayout类实现瀑布流步骤:

  1. 新建继承自UICollectionViewLayout的类。
  2. 重写以下方法。

下面介绍一下需要在UICollectionViewLayout子类中需要重写的方法,如下:

  • 重写prepareLayout函数:预加载布局函数

/**
 *  重写预加载布局函数,只会被执行一次
 */
- (void)prepareLayout {
    
    [super prepareLayout];
    
    // 初始化必要数据
    // 如:cell个数([self.collectionView numberOfSections]),cell宽度等
    
    // 初始化必要数据
    [self setupInitData];
    
    // 计算宽度
    [self setupCellWidth];
    
    // 随机高度
    [self setupCellHeight];
    
}

/**
 *  生成cell的随机高度,模拟不等高现象
 */
- (void)setupCellHeight {
    
    self.cellHeightArray = [[NSMutableArray alloc] initWithCapacity:self.numberCellsInSections];
    
    for (int i = 0 ; i < self.numberCellsInSections; i ++) {
        
        CGFloat cellHeight = arc4random() % (int)(self.cellMaxHeight - self.cellMinHeight) +
        self.cellMinHeight;
        
        [_cellHeightArray addObject:@(cellHeight)];
        
    }
    
}

/**
 *  计算cell的宽度
 */
- (void)setupCellWidth {
    
    // 每列cell的宽度相同
    self.cellWidth = (SCREEN_WIDTH - (HXColumnCount - 1) * HXCellsMargin) / HXColumnCount;
    
    // 计算每个cell的x坐标
    self.cellXArray = [[NSMutableArray alloc] initWithCapacity:HXColumnCount];
    
    for (int i = 0 ; i < HXColumnCount; i ++) {
        CGFloat tempX = i * (self.cellWidth + HXCellsMargin);
        
        [self.cellXArray addObject:@(tempX)];
    }
    
    
    
}

- (void)setupInitData {
    self.numberOfSections = [self.collectionView numberOfSections];
    self. numberCellsInSections = [self.collectionView numberOfItemsInSection:0];
    
    // 约束自动生成的图片的高度在100-200之间
    self.cellMinHeight = 100;
    self.cellMaxHeight = 200;
}
  • 重写collectionViewContentSize函数:设置滚动范围

/**
 *  重设滚动范围
 */
- (CGSize)collectionViewContentSize {
    
    CGFloat height = [self cellMaxYWithArray:self.cellYArray];
    
    return CGSizeMake(SCREEN_WIDTH, height);
    
}

- (CGFloat)cellMaxYWithArray:(NSMutableArray *)array {
    
    if (array.count == 0) {
        return 0.0;
    }
    
    CGFloat cellMaxY = [array[0] floatValue];// 默认第一个最大
    for (NSNumber *num in array) {
        
        CGFloat tempY = [num floatValue];
        
        if (tempY > cellMaxY) {
            cellMaxY = tempY;
        }
    }
    
    return cellMaxY;
    
}

  • 重写layoutAttributesForElementsInRect:函数:给每个cell绑定一个layoutAttributes属性,并返回
/**
 *  重写该方法,返回每个cell的layoutAttributes属性
 *  给每个cell绑定一个layoutAttributes属性
 */
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
    
    [self initCellYArray];// 初始化存储每列cell的y值数组
    
    NSMutableArray *array = [NSMutableArray array];
    
    for (int i = 0; i < self.numberCellsInSections; i ++) {
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
        
        UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath];
        
        [array addObject:attributes];
    }
    return array;
}

- (void)initCellYArray {
    
    self.cellYArray = [[NSMutableArray alloc] initWithCapacity:HXColumnCount];
    
    for (int i = 0; i < HXColumnCount; i ++) {
        [self.cellYArray addObject:@(0)];
    }
    
}

  • 重写layoutAttributesForItemAtIndexPath:函数:制定每个cell的layoutAttributes属性


/**
 *  指定每个cell的layoutAttributes属性
 */
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
    
    UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    
    CGRect frame = CGRectZero;
    
    CGFloat cellHeight = [self.cellHeightArray[indexPath.row] floatValue];
    int minYindex = [self cellMinYIndexWithArray:self.cellYArray];
    
    CGFloat tempX = [self.cellXArray[minYindex] floatValue];
    CGFloat tempY = [self.cellYArray[minYindex] floatValue];
    
    frame = CGRectMake(tempX, tempY, self.cellWidth, cellHeight);
    
    self.cellYArray[minYindex] = @(tempY + cellHeight + HXCellsMargin);
    
    // 绑定
    attributes.frame = frame;
    
    return attributes;
    
}

- (int)cellMinYIndexWithArray:(NSMutableArray *)array {
    
    if (array.count == 0) {
        return 0.0;
    }
    
    // 默认最小Y值、以及最小Y值对应的索引
    CGFloat min = [array[0] floatValue];
    int minIndex = 0;
    
    for (int i = 0 ; i < array.count; i ++) {
        
        CGFloat temp = [array[i] floatValue];
        
        if (temp < min) {
            min = temp;
            minIndex = i;
        }
    }
    
    return minIndex;
}
自定义完UICollectionViewLayout子类后,在控制器中使用它,如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    // 设置collectionView布局方式
    <span style="color:#FF0000;">HXCollectionViewFallLayout</span> *fallLayout = [[<span style="color:#FF0000;">HXCollectionViewFallLayout</span> alloc] init];
    
    // 创建collectionView
    UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:fallLayout];
    // 设置collectionView背景颜色
    collectionView.backgroundColor = [UIColor redColor];
    
    // 设置数据源和代理
    collectionView.dataSource = self;
    collectionView.delegate = self;
    
    // 注册一个collectionView Cell
    [collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"COLLECTIONCELL"];
    
    [self.view addSubview:collectionView];
    self.collectionView = collectionView;
    
}
将UICollectionView的布局模式设置成自定义的布局即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值