swift3实现瀑布流

//
//  ViewController.swift
//  TGWaterfall
//
//  Created by targetcloud on 2017/3/23.
//  Copyright © 2017年 targetcloud. All rights reserved.
//

import UIKit

private let kCollectionVCellID = "kCollectionVCellID"

class ViewController: UIViewController {
    
    var itemCount = 30
    
    fileprivate lazy var collectionView : UICollectionView = {
        let layout = TGWaterfallLayout()
        layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
        layout.minimumLineSpacing = 10
        layout.minimumInteritemSpacing = 10
        layout.cols = 2
        layout.dataSource = self
        let collectionV = UICollectionView(frame: self.view.bounds, collectionViewLayout: layout)
        collectionV.dataSource = self
        collectionV.delegate = self
        collectionV.register(UICollectionViewCell.self, forCellWithReuseIdentifier: kCollectionVCellID)
        return collectionV
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(collectionView)
        // Do any additional setup after loading the view, typically from a nib.
    }

}

extension ViewController:UICollectionViewDataSource{
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return itemCount
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: kCollectionVCellID, for: indexPath)
        cell.backgroundColor = UIColor.random()
        
        var label :UILabel? = cell.contentView.subviews.first as? UILabel
        if label == nil{
            label = UILabel(frame: cell.bounds)
            label?.textAlignment = .center
            cell.contentView.addSubview(label!)
        }
        label?.text = "\(indexPath.item)"
        
        /*
        如果代码打开的话,最后的 return cell 则不会执行到,导致循环利用CELL的BUG
        if itemCount - 1 == indexPath.item {
            itemCount += 30
            collectionView.reloadData()
        }
        */
        return cell
    }
}

extension ViewController:UICollectionViewDelegate{
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if scrollView.contentOffset.y > scrollView.contentSize.height - scrollView.bounds.height {//上拉加载更多效果
            itemCount += 30
            collectionView.reloadData()
        }
    }
}

extension ViewController:TGWaterfallLayoutDataSource{
    func waterfallLayout(_ layout: TGWaterfallLayout, itemIndex: Int) -> CGFloat {
        //return CGFloat(arc4random_uniform(150) + 50)
        let screenW = UIScreen.main.bounds.width
        return itemIndex % 2 == 0 ? screenW * 2 / 3 : screenW * 0.5
    }
}

TGWaterfallLayout的实现

//
//  TGWaterfallLayout.swift
//  TGWaterfall
//
//  Created by targetcloud on 2017/3/23.
//  Copyright © 2017年 targetcloud. All rights reserved.
//

import UIKit

protocol TGWaterfallLayoutDataSource:class {
    func waterfallLayout(_ layout :TGWaterfallLayout,itemIndex : Int) -> CGFloat
}

class TGWaterfallLayout: UICollectionViewFlowLayout {

    weak var dataSource : TGWaterfallLayoutDataSource?
    var cols = 4
    fileprivate lazy var attributes :[UICollectionViewLayoutAttributes] = [UICollectionViewLayoutAttributes]()
    fileprivate lazy var maxH : CGFloat = self.sectionInset.top + self.sectionInset.bottom
    fileprivate lazy var heights : [CGFloat] = Array(repeating: self.sectionInset.top, count: self.cols)
    override func prepare() {
        super.prepare()
        //attributes.removeAll()
        guard let collectionView = collectionView else {
            return
        }
        let count = collectionView.numberOfItems(inSection: 0)
        let itemW = (collectionView.bounds.width - sectionInset.left - sectionInset.right - CGFloat(cols-1) * minimumInteritemSpacing) / CGFloat(cols)
        
        for i in attributes.count..<count{
            /*
            //let itemH = CGFloat(arc4random_uniform(150) + 50)
            */
            //正式使用时请使用这里 
            guard let itemH = dataSource?.waterfallLayout(self, itemIndex: i) else{
                fatalError("请检查数据源")
            }
            
            /*
            let itemH = dataSource?.waterfallLayout(self, itemIndex: i) ?? CGFloat(arc4random_uniform(150) + 50)//test
            */
            let minH = heights.min()!
            let minIndex = heights.index(of: minH)!
            let itemX = sectionInset.left + (minimumInteritemSpacing + itemW) * CGFloat(minIndex)
            let indexPath = IndexPath(item: i, section: 0)
            let itemY = minH
            //heights[minIndex] = itemY
            let attribute = UICollectionViewLayoutAttributes(forCellWith: indexPath)
            attribute.frame = CGRect(x: itemX, y: itemY, width: itemW, height: itemH)
            attributes.append(attribute)
            heights[minIndex] = attribute.frame.maxY + minimumLineSpacing
            
        }
        
        maxH = heights.max()! - minimumLineSpacing
    }
    
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        return attributes
    }
    
    override var collectionViewContentSize: CGSize{
        return CGSize(width: 0, height: maxH + sectionInset.bottom)
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值