美文网首页
Swift版-CollectionView瀑布流框架搭建

Swift版-CollectionView瀑布流框架搭建

作者: Caiflower | 来源:发表于2016-06-20 15:58 被阅读450次

首先声明该Swift版是根据iOS-CollectionView瀑布流框架搭建这篇文章的OC版思路来实现的,
首先来个效果图:

瀑布流布局

思路:思路的话请看这iOS-CollectionView瀑布流框架搭建
这里就直接上代码啦

定义如下属性:

class GKWaterViewLayout: UICollectionViewLayout {
    // MARK: - 定义属性
    weak var delegate : GKWaterViewLayoutDelegate?
    /// 总列数
    var colCount : Int {
        return (delegate?.cloumnCountInWaterFlowLayout(self))!
        }
    /// 列间距
    var colMargin: CGFloat {
        return (delegate?.columMarginInWaterFlowLayout(self))!
    }
    /// 行间距
    var rowMargin: CGFloat {
        return (delegate?.rowMarginInWaterFlowLayout(self))!
    }
    /// 当前内边距
    var currentEdgeInsets: UIEdgeInsets {
        return (delegate?.edgeInsetInWaterFlowLayout(self))!
    }
    /// 布局属性数组
    private lazy var attrsArray = [UICollectionViewLayoutAttributes]()
    /// 存放所有列的当前高度
    private lazy var colHeights = [CGFloat]()
}

声明代理协议

  • 必须实现
// TODO:  由代理返回每一个cell的高度
protocol GKWaterViewLayoutDelegate: class {

    /// 返回每一个cell的高度
    func waterLayout(waterFlowLayout: GKWaterViewLayout,heightForRowAtIndex index: Int , itemWidth: CGFloat) -> CGFloat;
}
  • 可选实现
    • 代理未实现就使用默认值
// MARK: - 可选实现
extension GKWaterViewLayoutDelegate {
    /// 决定cell的列数
    func cloumnCountInWaterFlowLayout(waterFlowLayout: GKWaterViewLayout) -> Int {
        return 3
    }
    
    /// 决定cell 的列间距
    func columMarginInWaterFlowLayout(waterFlowLayout: GKWaterViewLayout) -> CGFloat {
        return 10.0
    }

    /// 决定cell 的行间距
    func rowMarginInWaterFlowLayout(waterFlowLayout: GKWaterViewLayout) -> CGFloat {
        return 10.0
    }

    /// 决定cell的边缘间距
    func edgeInsetInWaterFlowLayout(waterFlowLayout: GKWaterViewLayout) -> UIEdgeInsets {
        return UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
    }
}

重写布局相关方法

/// 布局相关
extension GKWaterViewLayout {
    
    override func prepareLayout() {
        super.prepareLayout()
        
        colHeights.removeAll()
        for _ in 0..<colCount {
            colHeights.append(currentEdgeInsets.top)
        }
        let count = collectionView?.numberOfItemsInSection(0)
        attrsArray.removeAll()
        
        for i in 0..<count! {
            let indexPath = NSIndexPath(forRow: i, inSection: 0)
            // 获取indexPath对应cell的布局属性
            let attr = self.layoutAttributesForItemAtIndexPath(indexPath)
            attrsArray.append(attr!)
        }
    }

    override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
        let attr = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)
        var destCol = 0
        var minColHeight = colHeights.first
        // 找出高度最短的那一列
        for i in 0..<colCount {
            let colHeight = colHeights[i]
            if minColHeight > colHeight {
                minColHeight = colHeight
                destCol = i
            }
        }
        // 计算每个item宽度
        // (collectionView宽度 - 左右间距 - 列间距) / 总列数
        let width = (collectionView?.frame.width)! - currentEdgeInsets.left - currentEdgeInsets.right
        let w = (width - CGFloat(colCount - 1) * colMargin) / CGFloat(colCount)
        // 使用代理决定外部cell的高度
        let h = delegate?.waterLayout(self, heightForRowAtIndex: indexPath.item, itemWidth: w)
        let x = currentEdgeInsets.left + CGFloat(destCol) * (w + colMargin)
        var y = minColHeight
        if y != currentEdgeInsets.top {
            y = y! + rowMargin
        }
        attr.frame = CGRect(x: x, y: y!, width: w, height: h!)
        colHeights[destCol] = y! + h!
        return attr
    }
    /// 这个方法返回值是个数组,存放的是UICollectionViewLayoutAttributes对象
    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        return attrsArray
    }
    /// 决定collectionView的可滚动范围
    override func collectionViewContentSize() -> CGSize {
        var maxHeight: CGFloat = colHeights.first!
        for i in 0..<colCount {
            let value: CGFloat = colHeights[i]
            if maxHeight < value {
                maxHeight = value
            }
        }
        return CGSize(width: 0, height: maxHeight + currentEdgeInsets.bottom)
    }
}
到此,CollectionView瀑布流框架搭建完成了! Demo下载地址Demo下载地址

如果好用,请点上star,谢谢

相关文章

网友评论

      本文标题:Swift版-CollectionView瀑布流框架搭建

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