1

Currently, I manually calculate the height of each cell depending upon how much height the labels and images would take. I have a square shaped image whose length is equal to width of the screen. But I am looking for other alternative where I don't have to do this manually. I want something like tableview where it is auto-calculated based on constraints.

  • Read this stackoverflow post [here](https://stackoverflow.com/questions/28161839/uicollectionview-dynamic-cell-height) – lopes710 Nov 15 '17 at 18:51
  • "something like tableview where it is auto-calculated based on constraints" Unfortunately, although Apple has repeatedly _claimed_ that UICollectionView has such a feature, it has never worked as advertised. You just have out the size yourself. – matt Nov 15 '17 at 19:26

1 Answers1

0

Here's a little setup that will help you.

Apple gives several options for UICollectionView cell sizing: 1. Autolayout, 2. override sizeThatFits() or 3. override preferredLayoutAttributesFittingattributes()

You can watch WWDC 2016 video session 219 for more info.

Autolayout option below.

Created a UICollectionViewCell subclass, xib, with a text label. In view controller created collectionView, added as subview, registered xib, set up UICollectionViewFlowLayout with estimated size 1x1. UICollectionView will calculate height out of the box.

class ViewController: UIViewController {
    var collectionView: UICollectionView? {
        didSet {
            let nib = UINib.init(nibName: "Cell", bundle: nil)
            collectionView?.register(nib, forCellWithReuseIdentifier: "Cell")
        }
    }

    let dataSource: [String] = ["test test test test test",
                                "test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test"]

    override func viewDidLoad() {
        super.viewDidLoad()
        let flowLayout = UICollectionViewFlowLayout()
        // Don't miss this line, or collectionView will use autosizing by default
        flowLayout.estimatedItemSize = CGSize(width: 1, height: 1)
        let collection = UICollectionView(frame: view.bounds, collectionViewLayout: flowLayout)
        view.addSubview(collection)
        collectionView = collection
        collectionView?.dataSource = self
    }
}

extension ViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return dataSource.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
        cell.descriptionLabel.text = dataSource[indexPath.row]
        return cell
    }
}

Cell setup:

@IBOutlet weak var widthLayoutConstraint: NSLayoutConstraint!

override func awakeFromNib() {
    super.awakeFromNib()
    // We dont need autolayout calculation for width and height of the cell so disabling it
    contentView.translatesAutoresizingMaskIntoConstraints = false
    // And adding a constant width constraint
    let width = UIScreen.main.bounds.size.width
    widthLayoutConstraint.constant = width - 24.0 // giving some offsets for the cell: 24 pt
}

Also be aware that this setup will not work for iOS < 9.

marc_s
  • 675,133
  • 158
  • 1,253
  • 1,388
Oleh Zayats
  • 2,233
  • 1
  • 14
  • 24