Chris Hansen
Chris Hansen

Reputation: 8687

Showing random number of items per line

I have 15 categories that I want to show on the screen. I want to do the following

Someone said using collection view compositional layout is the way to go. Here's what I have so far. Unfortunately, it's not rendering the categories properly. See screenshot.

import UIKit

class CategoriesViewController: UIViewController, UICollectionViewDataSource {
    var categories = ["Category 1", "Category 2", "Category 3", "Category 4", "Category 5", 
                      "Category 6", "Category 7", "Category 8", "Category 9", "Category 10"]
    var collectionView: UICollectionView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        
        // Initialize collection view with a compositional layout
        collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: createLayout())
        collectionView.dataSource = self
        collectionView.register(CategoryCell.self, forCellWithReuseIdentifier: "CategoryCell")
        collectionView.backgroundColor = .white
        view.addSubview(collectionView)
    }
    
    // MARK: - Compositional Layout
    
    func createLayout() -> UICollectionViewLayout {
        let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.2), heightDimension: .absolute(50))
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        
        // Add spacing between items
        item.contentInsets = NSDirectionalEdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5)
        
        let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(60))
        let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
        
        let section = NSCollectionLayoutSection(group: group)
        section.interGroupSpacing = 10
        
        let layout = UICollectionViewCompositionalLayout(section: section)
        return layout
    }
    
    // MARK: - UICollectionViewDataSource
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return categories.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CategoryCell", for: indexPath) as! CategoryCell
        cell.configure(with: categories[indexPath.item])
        return cell
    }
}

enter image description here

Upvotes: 0

Views: 85

Answers (1)

MinhNghien26
MinhNghien26

Reputation: 9

I have the same issue and this is how I can fix it.

  • First: You don’t need to create a new layout.

But remember to choose Collection View -> Size Inspector -> Estimate Size set to None.

This will let you conform to UICollectionViewDelegateFlowLayout.

extension BaseViewController: UICollectionViewDelegateFlowLayout {
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 8
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 8
    }
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let itemWidth = ((collectionView.bounds.width - 16)/3)
        return CGSize(width: itemWidth, height: itemWidth * 235/125)
    }
}

If you have 3 items in a row, the spacing between items is 8. The width of each item is calculated as: Width = (CollectionView.Width - 16) / 3. For 5 items, the formula becomes: Width = (CollectionView.Width - 32) / 5.

235/125 represents the ratio of your cell:

let itemWidth = ((collectionView.bounds.width - 16)/3)
return CGSize(width: itemWidth, height: itemWidth * 235/125)

Upvotes: 0

Related Questions