UICollectionView动态自定义布局
UICollectionView dynamic custom layout
我正在尝试创建一个 UICollectionView,其布局类型与我附加的图像相同。我对如何实现这种布局有点困惑。
谷歌搜索后,我似乎需要编写一个自定义的 UICollectionViewFlowLayout,但我似乎找不到任何每个项目具有不同节数的布局示例。
如果您查看模型,第一项有一个部分。图像是风景,但中间项目有 2 个部分和 2 个肖像图像。
我是不是看错东西了?有人能指出我正确的方向吗?
您可以使用 UICollectionViewDelegateFlowLayout
执行此操作,无需子类化。
这是一个例子:
import UIKit
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
}
// MARK: - UICollectionViewDataSource
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("TestCollectionViewCell", forIndexPath: indexPath) as! UICollectionViewCell
if indexPath.item % 3 == 0 {
cell.backgroundColor = UIColor.redColor()
} else {
cell.backgroundColor = UIColor.greenColor()
}
return cell
}
// MARK: - UICollectionViewDelegateFlowLayout
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
if indexPath.item % 3 == 0 {
let cellWidth = (CGRectGetWidth(collectionView.frame) - (flowLayout.sectionInset.left + flowLayout.sectionInset.right))
return CGSize(width: cellWidth, height: cellWidth / 2)
} else {
let cellWidth = (CGRectGetWidth(collectionView.frame) - (flowLayout.sectionInset.left + flowLayout.sectionInset.right) - flowLayout.minimumInteritemSpacing) / 2
return CGSize(width: cellWidth, height: cellWidth)
}
}
}
我喜欢 Jacob Howcroft 的回答,我发现 UICollectionViewDelegateFlowLayout 方法可以改进:
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
var numberOfCellsPerLine = 0
if indexPath.item % 3 == 0 {
numberOfCellsPerLine = 1
} else {
numberOfCellsPerLine = 2
}
// Generic cell width calculation
let cellWidth = (collectionView.bounds.width - (flowLayout.sectionInset.left + flowLayout.sectionInset.right)
- flowLayout.minimumInteritemSpacing * CGFloat(numberOfCellsPerLine - 1)) / CGFloat(numberOfCellsPerLine)
return CGSize(width: cellWidth, height: 100)
}
根据 indexPath,这使得每行需要多少个单元格变得更加明显(您可以根据需要使用 "if / else" 或开关)。
此外,它使这段代码超级可重用,因为您总是必须考虑相同的元素(section inset,minimumInterItemSpacing)。
我正在尝试创建一个 UICollectionView,其布局类型与我附加的图像相同。我对如何实现这种布局有点困惑。
谷歌搜索后,我似乎需要编写一个自定义的 UICollectionViewFlowLayout,但我似乎找不到任何每个项目具有不同节数的布局示例。
如果您查看模型,第一项有一个部分。图像是风景,但中间项目有 2 个部分和 2 个肖像图像。
我是不是看错东西了?有人能指出我正确的方向吗?
您可以使用 UICollectionViewDelegateFlowLayout
执行此操作,无需子类化。
这是一个例子:
import UIKit
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
}
// MARK: - UICollectionViewDataSource
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("TestCollectionViewCell", forIndexPath: indexPath) as! UICollectionViewCell
if indexPath.item % 3 == 0 {
cell.backgroundColor = UIColor.redColor()
} else {
cell.backgroundColor = UIColor.greenColor()
}
return cell
}
// MARK: - UICollectionViewDelegateFlowLayout
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
if indexPath.item % 3 == 0 {
let cellWidth = (CGRectGetWidth(collectionView.frame) - (flowLayout.sectionInset.left + flowLayout.sectionInset.right))
return CGSize(width: cellWidth, height: cellWidth / 2)
} else {
let cellWidth = (CGRectGetWidth(collectionView.frame) - (flowLayout.sectionInset.left + flowLayout.sectionInset.right) - flowLayout.minimumInteritemSpacing) / 2
return CGSize(width: cellWidth, height: cellWidth)
}
}
}
我喜欢 Jacob Howcroft 的回答,我发现 UICollectionViewDelegateFlowLayout 方法可以改进:
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
var numberOfCellsPerLine = 0
if indexPath.item % 3 == 0 {
numberOfCellsPerLine = 1
} else {
numberOfCellsPerLine = 2
}
// Generic cell width calculation
let cellWidth = (collectionView.bounds.width - (flowLayout.sectionInset.left + flowLayout.sectionInset.right)
- flowLayout.minimumInteritemSpacing * CGFloat(numberOfCellsPerLine - 1)) / CGFloat(numberOfCellsPerLine)
return CGSize(width: cellWidth, height: 100)
}
根据 indexPath,这使得每行需要多少个单元格变得更加明显(您可以根据需要使用 "if / else" 或开关)。
此外,它使这段代码超级可重用,因为您总是必须考虑相同的元素(section inset,minimumInterItemSpacing)。