美文网首页
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