首頁在展示大量圖片的時候, 如果內容尺寸不一致, 除了直接裁剪圖片, 還可以使用瀑布式布局, 看起來也很美觀.
例如花瓣網
花瓣網
我們也可以使用 CollectionView 實現類似的效果.
如圖所示
demo
CollectionView
相較之下, 很多同學可能對 CollectionView 比較陌生, 其實想對于常用的 TableView, CollectionView 就只是多了一個布局, 你完全可以用 CollectionView 加上一個布局文件模擬出一個 TableView 的效果
布局類
布局類需要繼承自UICollectionViewLayout, 并實現
這幾個方法
prepare
layoutAttributesForElements:in
collectionViewContentSize
prepare
方法中, 我們在這里準備好了每個元素的布局, 然后在layoutAttributesForElements:in
中返回對應區域的布局信息. collectionViewContentSize
用于獲取內容尺寸, 類似于ScrollView
的 ContentSize
準備布局
每一列的列數目, 需要定下來, 我們這里為3列.
瀑布式布局, 其實就是所有元素一個一個挨著放下來就行了.
代碼如下
override func prepare() {
self.layoutInfo.removeAll()
self.contentHeight = 0
let width = (self.collectionView!.frame.size.width - (self.columnsCount + 1) * self.space) / self.columnsCount
var currentY: [CGFloat] = [self.space, self.space, self.space]
for section in 0 ..< self.collectionView!.numberOfSections {
for item in 0 ..< self.collectionView!.numberOfItems(inSection: section) {
let indexPath = IndexPath(item: item, section: section)
let attribute = UICollectionViewLayoutAttributes(forCellWith: indexPath)
var column = 0
var minY = currentY[0]
for i in 0 ..< currentY.count {
if minY > currentY[i] {
minY = currentY[i]
column = i
}
}
let x = self.space + CGFloat(column) * (self.space + width)
let y = currentY[column]
let height = self.delegate.heightFor(itemAtIndexPath: indexPath, withWidth: width)
attribute.frame = CGRect(x: x, y: y, width: width, height: height)
self.layoutInfo[indexPath] = attribute
currentY[column] += height + self.space
self.contentHeight = max(currentY[column], self.contentHeight)
}
}
}
這里使用了一個layoutInfo
字典用來存放每個元素的布局信息.
self.space
表示了元素之前的間隙, self.contentHeight
則用來存放內容高度
獲取對應區域布局信息
當某塊區域需要顯示的時候, 會調用layoutAttributesForElements:in
來獲取對應區域的布局.
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var attributes = [UICollectionViewLayoutAttributes]()
for (_, attribute) in self.layoutInfo {
if attribute.frame.intersects(rect) {
attributes.append(attribute)
}
}
return attributes
}
獲取內容高度
由于我們之前在準備的時候, 已經計算好了內容高度, 這里直接使用就可以了
override var collectionViewContentSize: CGSize {
return CGSize(width: self.collectionView!.frame.size.width, height: self.contentHeight)
}
這樣就大功告成了. demo可以點這里https://github.com/ywwzwb/CollectionViewDemo