Dynamic collection view cell column from different iPhone device

I try to create a dynamic cell column from different iPhone devices with collectionView.

I already try for iPhone SE to have a 3 column and success, but when I try to make iPhone 11 Pro Max to have a 4 column it have a space between each cell.

iPhone 11 Pro Max

iPhone pro max

iPhone SE

iPhone SE

I calculate my cell like this

enum UIHelper {
    static func createCollectionViewFlowLayout() -> UICollectionViewFlowLayout {
        let screenWidth                     = UIScreen.main.bounds.width
        let padding: CGFloat                = 12
        let minimumInterimSpacing: CGFloat  = 10
        let availableWidth                  = screenWidth - (padding * 2) - (minimumInterimSpacing * 2)
        var numberOfColumn: CGFloat
        
        // 375 is iPhone SE width
        if screenWidth > 375 {
            numberOfColumn = 4
        } else {
            numberOfColumn = 3
        }
        
        let itemWidth                       = availableWidth / numberOfColumn
        
        let flowLayout                      = UICollectionViewFlowLayout()
        flowLayout.sectionInset             = UIEdgeInsets(top: padding, left: padding, bottom: padding, right: padding)
        flowLayout.itemSize                 = CGSize(width: itemWidth, height: itemWidth)
        
        return flowLayout
    }
}

and in my view controller I create it like this

override func viewDidLoad() {
   super.viewDidLoad()
        
   collectionView.delegate = self
   collectionView.dataSource = self
   collectionView.collectionViewLayout = UIHelper.createCollectionViewFlowLayout()
}

what am I missing?


Solution 1:

Your setup seems to be fine, The issue seems to be with the logic / math in this line

let availableWidth = screenWidth - (padding * 2) - (minimumInterimSpacing * 2)

The logic is that if you have 3 cells in a row, there will be 2 gaps between the 3 cells, but if you have 4 cells in a row, you will have 3 gaps.

UICollectionView UICollectionViewFlowLayout

So if I change the available width also based on the number of cells I intend to have, you will get the desired results. So I have made some small changes to change the available width based on how many cells you want in a row.

I have made some minor edits to your code, I have included some comments to show what I have changed, however, you will need to organize my updates better as I made quick changes to show you the fix in the logic.

static func createCollectionViewFlowLayout() -> UICollectionViewFlowLayout {
        let screenWidth                     = UIScreen.main.bounds.width
        let padding: CGFloat                = 12
        let minimumInterimSpacing: CGFloat  = 10
        
        // Updated this to a var
        var availableWidth                  = screenWidth - (padding * 2) - (minimumInterimSpacing * 2)
        
        var numberOfColumn: CGFloat
        
        // 375 is iPhone SE width
        if screenWidth > 375 {
            numberOfColumn = 4
            
            // Update the width available as well
            availableWidth = screenWidth - (padding * 2) - (minimumInterimSpacing * (numberOfColumn - 1))
        } else {
            numberOfColumn = 3
        }
        
        let itemWidth                       = availableWidth / numberOfColumn
        print(numberOfColumn)
        
        let flowLayout                      = UICollectionViewFlowLayout()
        flowLayout.minimumInteritemSpacing  = minimumInterimSpacing
        flowLayout.sectionInset             = UIEdgeInsets(top: padding, left: padding, bottom: padding, right: padding)
        flowLayout.itemSize                 = CGSize(width: itemWidth, height: itemWidth)
        
        return flowLayout
}