I have a working default collection view flow layout but I am trying to have my cells left aligned (not the default center stretch). I got some good answers from this post. It says I need to use a custom layout. But how do you even implement a custom layout? I created a file and it is ready to go but how do I hook it up to the VC with the Collection View?
Here is what is in my Collection View's VC: created an outlet for the layout at top
@IBOutlet weak var tagsLayout: TagsLayout!
My current implementation of default flow layout at bottom:
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
}
}
I've seen this may be necessary in viewdidload but .delegate is not recognized / not in my custom layout
if let layout = self.collectionView.collectionViewLayout as? TagsLayout
{
layout.delegate = self
}
TagsLayout:
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
}
}
Simply set the delegate
of collectionView
to self
in the viewDidLoad
method of ItemViewController
.
class ItemViewController: UIViewController {
@IBOutlet weak var tagsLayout: TagsLayout!
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
collectionView.collectionViewLayout = tagsLayout
collectionView.delegate = self
}
}
Then you can verify by simply:
extension ItemViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
print("Now it getting called... :)")
//...
}
}