首先聲明該Swift版是根據(jù)iOS-CollectionView瀑布流框架搭建這篇文章的OC版思路來(lái)實(shí)現(xiàn)的,
首先來(lái)個(gè)效果圖:
瀑布流布局
思路:思路的話請(qǐng)看這iOS-CollectionView瀑布流框架搭建
這里就直接上代碼啦
定義如下屬性:
class GKWaterViewLayout: UICollectionViewLayout {
// MARK: - 定義屬性
weak var delegate : GKWaterViewLayoutDelegate?
/// 總列數(shù)
var colCount : Int {
return (delegate?.cloumnCountInWaterFlowLayout(self))!
}
/// 列間距
var colMargin: CGFloat {
return (delegate?.columMarginInWaterFlowLayout(self))!
}
/// 行間距
var rowMargin: CGFloat {
return (delegate?.rowMarginInWaterFlowLayout(self))!
}
/// 當(dāng)前內(nèi)邊距
var currentEdgeInsets: UIEdgeInsets {
return (delegate?.edgeInsetInWaterFlowLayout(self))!
}
/// 布局屬性數(shù)組
private lazy var attrsArray = [UICollectionViewLayoutAttributes]()
/// 存放所有列的當(dāng)前高度
private lazy var colHeights = [CGFloat]()
}
聲明代理協(xié)議
- 必須實(shí)現(xiàn)
// TODO: 由代理返回每一個(gè)cell的高度
protocol GKWaterViewLayoutDelegate: class {
/// 返回每一個(gè)cell的高度
func waterLayout(waterFlowLayout: GKWaterViewLayout,heightForRowAtIndex index: Int , itemWidth: CGFloat) -> CGFloat;
}
- 可選實(shí)現(xiàn)
- 代理未實(shí)現(xiàn)就使用默認(rèn)值
// MARK: - 可選實(shí)現(xiàn)
extension GKWaterViewLayoutDelegate {
/// 決定cell的列數(shù)
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)
}
}
重寫布局相關(guān)方法
/// 布局相關(guān)
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對(duì)應(yīng)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
}
}
// 計(jì)算每個(gè)item寬度
// (collectionView寬度 - 左右間距 - 列間距) / 總列數(shù)
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
}
/// 這個(gè)方法返回值是個(gè)數(shù)組,存放的是UICollectionViewLayoutAttributes對(duì)象
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return attrsArray
}
/// 決定collectionView的可滾動(dòng)范圍
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下載地址
如果好用,請(qǐng)點(diǎn)上star,謝謝