首先声明该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下载地址
如果好用,请点上star,谢谢
网友评论