Search code examples
swiftuicollectionviewuicollectionviewcellnslayoutconstraintuicollectionviewlayout

collectionViewCells to collectionView position x:0, y:0


I am experiencing some layout issues with collectionViewCells. I am programmatically applying layout constraints and UICollectionViewCells are not being pinned to the 0,0 position in my collectionView. See attached screenshot for reference. Thanks in advance!

class CurrentUserPlaceDetailsVC: UIViewController, UICollectionViewDelegateFlowLayout {

    override func viewDidLoad() {
        super.viewDidLoad()

        setupMenuBar()
    }

    let menuBar: MenuBar = {
        let mb = MenuBar()
        return mb
    }()

    private func setupMenuBar() {
        view.addSubview(menuBar)
        view.addConstraintsWithFormat("H:|[v0]|", views: menuBar)
        view.addConstraintsWithFormat("V:|-64-[v0(150)]", views: menuBar)

    }
    var placesTableVC: PlacesTableVC?
}

class MenuBar: UIView, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {

    lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cv.backgroundColor = UIColor.green
        cv.dataSource = self
        cv.delegate = self
        return cv
    }()

    let cellId = "cellId"

    override init(frame: CGRect) {
        super.init(frame: frame)


        collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cellId)

        addSubview(collectionView)
        addConstraintsWithFormat("H:|[v0]|", views: collectionView)
        addConstraintsWithFormat("V:|[v0]|", views: collectionView)

    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 4
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)
        cell.backgroundColor = .blue
        return cell
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}


extension UIView {

    func addConstraintsWithFormat(_ format: String, views: UIView...) {
        var viewsDictionary = [String: UIView]()
        for (index, view) in views.enumerated() {
            let key = "v\(index)"
            view.translatesAutoresizingMaskIntoConstraints = false
            viewsDictionary[key] = view
        }

        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutFormatOptions(), metrics: nil, views: viewsDictionary))
    }

enter image description here


Solution

  • You need to set the minimumLineSpacing, headerReferenceSize, and/or sectionInset of the UICollectionViewFlowLayout instance you use to initialize your UICollectionView. You can also set the contentInset of the UICollectionView.

    Try this:

    lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.minimumLineSpacing = 0
        layout.headerReferenceSize = .zero
        layout.sectionInset = .zero
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cv.backgroundColor = .green
        cv.dataSource = self
        cv.delegate = self
        cv.contentInset = .zero
        return cv
    }()