iOS - 实施自定义 collection 视图布局
iOS - implementing custom collection view layout
我有一个可用的默认 collection 视图流布局,但我试图让我的单元格左对齐(不是默认的中心拉伸)。我从 this post 那里得到了一些很好的答案。它说我需要使用自定义布局。但是你如何实现自定义布局呢?我创建了一个文件,它已准备就绪,但如何将它连接到 VC 和 Collection 视图?
这是我的 Collection 视图 VC 中的内容:
为顶部的布局创建了一个出口
@IBOutlet weak var tagsLayout: TagsLayout!
我目前在底部实现的默认流布局:
extension ItemViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let text = allTags[indexPath.row]
let font: UIFont = UIFont(name: "Baskerville", size: 15) ?? UIFont.systemFont(ofSize: 17.0) // set here font name and font size
let width = text.SizeOf(font).width
return CGSize(width: width + 20.0 , height: 30.0) // ADD width + space between text (for ex : 20.0)
}
//
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt: Int) -> CGFloat {
return 4.0
}
}
我发现这在 viewdidload 中可能是必需的,但 .delegate 无法识别/不在我的自定义布局中
if let layout = self.collectionView.collectionViewLayout as? TagsLayout
{
layout.delegate = self
}
标签布局:
import UIKit
class TagsLayout: UICollectionViewFlowLayout {
required override init() {super.init(); common()}
required init?(coder aDecoder: NSCoder) {super.init(coder: aDecoder); common()}
private func common() {
estimatedItemSize = UICollectionViewFlowLayout.automaticSize
minimumLineSpacing = 10
minimumInteritemSpacing = 10
}
override func layoutAttributesForElements(
in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let att = super.layoutAttributesForElements(in:rect) else {return []}
var x: CGFloat = sectionInset.left
var y: CGFloat = -1.0
for a in att {
if a.representedElementCategory != .cell { continue }
if a.frame.origin.y >= y { x = sectionInset.left }
a.frame.origin.x = x
x += a.frame.width + minimumInteritemSpacing
y = a.frame.maxY
}
return att
}
}
只需在ItemViewController
的viewDidLoad
方法中将collectionView
的delegate
设置为self
即可。
class ItemViewController: UIViewController {
@IBOutlet weak var tagsLayout: TagsLayout!
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
collectionView.collectionViewLayout = tagsLayout
collectionView.delegate = self
}
}
那么你可以通过简单的验证:
extension ItemViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
print("Now it getting called... :)")
//...
}
}
我有一个可用的默认 collection 视图流布局,但我试图让我的单元格左对齐(不是默认的中心拉伸)。我从 this post 那里得到了一些很好的答案。它说我需要使用自定义布局。但是你如何实现自定义布局呢?我创建了一个文件,它已准备就绪,但如何将它连接到 VC 和 Collection 视图?
这是我的 Collection 视图 VC 中的内容: 为顶部的布局创建了一个出口
@IBOutlet weak var tagsLayout: TagsLayout!
我目前在底部实现的默认流布局:
extension ItemViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let text = allTags[indexPath.row]
let font: UIFont = UIFont(name: "Baskerville", size: 15) ?? UIFont.systemFont(ofSize: 17.0) // set here font name and font size
let width = text.SizeOf(font).width
return CGSize(width: width + 20.0 , height: 30.0) // ADD width + space between text (for ex : 20.0)
}
//
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt: Int) -> CGFloat {
return 4.0
}
}
我发现这在 viewdidload 中可能是必需的,但 .delegate 无法识别/不在我的自定义布局中
if let layout = self.collectionView.collectionViewLayout as? TagsLayout
{
layout.delegate = self
}
标签布局:
import UIKit
class TagsLayout: UICollectionViewFlowLayout {
required override init() {super.init(); common()}
required init?(coder aDecoder: NSCoder) {super.init(coder: aDecoder); common()}
private func common() {
estimatedItemSize = UICollectionViewFlowLayout.automaticSize
minimumLineSpacing = 10
minimumInteritemSpacing = 10
}
override func layoutAttributesForElements(
in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let att = super.layoutAttributesForElements(in:rect) else {return []}
var x: CGFloat = sectionInset.left
var y: CGFloat = -1.0
for a in att {
if a.representedElementCategory != .cell { continue }
if a.frame.origin.y >= y { x = sectionInset.left }
a.frame.origin.x = x
x += a.frame.width + minimumInteritemSpacing
y = a.frame.maxY
}
return att
}
}
只需在ItemViewController
的viewDidLoad
方法中将collectionView
的delegate
设置为self
即可。
class ItemViewController: UIViewController {
@IBOutlet weak var tagsLayout: TagsLayout!
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
collectionView.collectionViewLayout = tagsLayout
collectionView.delegate = self
}
}
那么你可以通过简单的验证:
extension ItemViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
print("Now it getting called... :)")
//...
}
}