Search code examples
iosswiftuicollectionviewuicollectionviewcelluicollectionviewlayout

How to match the horizontal collectionView Cell's width on it's content size


I know some related questions already there regarding this but I tried those before and still no luck.

Here is my problem on the following screenshot my current collectionView My current screen shows a fixed cell size and it displays empty spaces for smaller contents and larger contents going over the cell with dots..

I wanted like below enter image description here it should match the width of the product category name content.

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    if collectionView == self.catCollectionView{
        let catCell = collectionView.dequeueReusableCell(withReuseIdentifier: "catCell", for: indexPath)
            as! catCell

        DispatchQueue.main.async {
            catCell.configureCell()

            let catCountInt = self.catCountArray[indexPath.row]


            catCell.catCountLabel.text = String(catCountInt)
            catCell.catNameLabel.text = self.categoryNameArray[indexPath.row]
            catCell.catCountLabel.sizeToFit()
            catCell.catNameLabel.sizeToFit()

        }
        return catCell
 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let catCell = collectionView.dequeueReusableCell(withReuseIdentifier: "catCell", for: indexPath)
        as! catCell
    catCell.catNameLabel.text = self.categoryNameArray[indexPath.item]
    catCell.catNameLabel.sizeToFit()
     let labelWidth = catCell.catNameLabel.frame.width + 10
    print("frame width: \(labelWidth)")
    return CGSize(width: labelWidth, height: 21)
}

}

Maybe I'm missing a simple thing here but I couldn't quite figure out at this moment. Please help me and sorry for my strange English.


Solution

  • Let's imagine you are using a simple UICollectionViewCell subclass with constraints set up correctly in storyboard (label is pinned to all four sides of its superview) like this:

    class CategoryCell: UICollectionViewCell {
    
        @IBOutlet var nameLabel: UILabel!
    
        override func awakeFromNib() {
            super.awakeFromNib()
            layer.borderWidth = 1
        }
    
    }
    

    Then you can simply let auto layout determine the cells' sizes:

    class CollectionViewController: UICollectionViewController {
    
        let categories = [
            "All Products",
            "Fresh",
            "Health & Beauty",
            "Beverages",
            "Home & life"
        ]
    
        private var flowLayout: UICollectionViewFlowLayout? {
            return collectionViewLayout as? UICollectionViewFlowLayout
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            collectionView.backgroundColor = .white
    
            flowLayout?.sectionInset = .init(top: 15, left: 15, bottom: 15, right: 15)
            flowLayout?.sectionInsetReference = .fromSafeArea
            flowLayout?.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
    
            DispatchQueue.main.async {
                self.flowLayout?.invalidateLayout()
            }
        }
    
        override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return categories.count
        }
    
        override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CategoryCell", for: indexPath) as! CategoryCell
            cell.nameLabel.text = categories[indexPath.row]
            return cell
        }
    
    }
    

    Result:

    result