0

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
    }
}
byJeevan
  • 3,728
  • 3
  • 37
  • 60
TrevPennington
  • 435
  • 5
  • 15

1 Answers1

2

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... :)")
        //...
    }
}
Frankenstein
  • 15,732
  • 4
  • 22
  • 47
  • Just updated my post right before you sent that to say I have that but .delegate is not recognized / not part of my custom layout. How does that delegate method look in the custom layout class? Thanks – TrevPennington Aug 18 '20 at 13:57
  • What is `TagsLayout` inheriting from? Add the `TagsLayout` code to your question. – Frankenstein Aug 18 '20 at 13:59
  • ```UICollectionViewFlowLayout``` added. – TrevPennington Aug 18 '20 at 14:00
  • Okay, so where are you assigning this layout to the `collectionView`? I've just updated the code above. You'll have to set the `delegate` of `collectionView` to `self`. I've added the code to set the layout to the `collectionView` above. – Frankenstein Aug 18 '20 at 14:03
  • That's my question lol. Not sure how to do that. I set the custom layout in IB and hooked it up to the outlet I posted. – TrevPennington Aug 18 '20 at 14:07