Collection View 自定义布局(custom flow layout)

Collection view自定义布局

一般我们自定义布局都会新建一个类,继承自UICollectionViewFlowLayout,然后重写几个方法:

  • prepareLayout():当准备开始布局时调用这个方法,可以在这里计算一些属性,比如cell的尺寸。
  • layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]?:在这里返回布局属性。

 

实例(比较简单的例子,实际开发中可以进行更多的封装)

第一步:声明两个属性

    // MARK: 属性
    /** cell的个数 */
    var itemCount: Int?
    
    /** 布局信息 */
    var layoutAttributes = [UICollectionViewLayoutAttributes]()

第二步:重写prepareLayout方法,计算布局属性

    // MARK: 准备布局
    override func prepareLayout() {
        super.prepareLayout()
        
        // 计算每个cell的宽度
        let width = (UIScreen.mainScreen().bounds.size.width - self.sectionInset.left - self.sectionInset.right - minimumInteritemSpacing) / 2.0
        
        // 判断itemCount是否为空
        if itemCount != nil {
            // 开始计算每个cell的布局属性
            calculationAttribute(withItemWidth: width)
        }
    }

 

func calculationAttribute(withItemWidth itemWidth: CGFloat) {
        // 声明数组 保存每一列的总高度 (两列)
        let column1 = sectionInset.top, column2 = sectionInset.top
        var columnArray: [CGFloat] = [column1, column2]
        
        for index in 0..<itemCount! {
            // 创建indexPath 因为是示例 所以排版固定在一组
            let indexPath = NSIndexPath(forItem: index, inSection: 0)
            // 创建布局属性 通过indexPath
            let attribute = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)
            // 创建一个随机高度
            let itemHeight = CGFloat(arc4random()%150 + 100)
            
            // columnNumber 记录定义的是哪一列
            var columnNumber: CGFloat
            if columnArray[0] < columnArray[1] {
                columnArray[0] += itemHeight + self.minimumLineSpacing
                columnNumber = 0
            } else {
                columnArray[1] += itemHeight + self.minimumLineSpacing
                columnNumber = 1
            }
            
            // 设置item的位置
            let x = self.sectionInset.left + (self.minimumLineSpacing + itemWidth) * columnNumber
            let y = columnArray[Int(columnNumber)] - itemHeight - self.minimumLineSpacing
            attribute.frame = CGRectMake(x, y, itemWidth, itemHeight)
            
            layoutAttributes.append(attribute)
        }
        // 当设置完所有item的位置后需要设置itemsize 这样才能保证滚动时能显示所有的cell
        // itemsize的height属性 是取最高的那列的平均值
        if columnArray[0] > columnArray[1] {
            self.itemSize = CGSizeMake(itemWidth, (columnArray[0] - sectionInset.top) * 2 / CGFloat(itemCount!) - self.minimumLineSpacing)
        } else {
            self.itemSize = CGSizeMake(itemWidth, (columnArray[1] - sectionInset.top) * 2 / CGFloat(itemCount!) - self.minimumLineSpacing)
        }
    }

 第三步:返回布局信息数组

    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        return layoutAttributes
    }

 

总结:这个例子是瀑布流的布局,如果需要别的布局需要在准备布局时计算,然后返回布局信息数组就可以了

posted @ 2016-06-09 13:48  Alex_sun  阅读(374)  评论(0编辑  收藏  举报