I am trying to create UICollectionView programatically, and my cells are getting stacked vertically instead of a grid form.
My code is:
let layout:UICollectionViewFlowLayout = UICollectionViewFlowLayout()
let screenSize: CGRect = UIScreen.main.bounds
let screenWidth = screenSize.width
let width = (screenWidth - 4)/3
layout.itemSize = CGSize(width: width, height: width+20)
layout.sectionInset = UIEdgeInsets(top:0,left:0,bottom:0,right:0)
collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
collectionView?.dataSource = self
collectionView?.delegate=self
collectionView?.collectionViewLayout = layout
collectionView?.register(NearbyCollectionViewCell.self, forCellWithReuseIdentifier: "cellId")
self.view.addSubview(collectionView!)
You should always consider collectionView
's frame for item size calculation.
In your question you are using UIScreen
's width which might get you to wrong calculations because of collectionView
's inset
properties.
let screenSize: CGRect = UIScreen.main.bounds
let screenWidth = screenSize.width
For correct size calculation lets define the number of items in single row.
let maximumItemInRow = 3
(You can play with this as per your requirement)
Now implementing the UICollectionViewDelegateFlowLayout
's sizeForItem
method.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// Getting collectionView's size
var width = collectionView.frame.width
var height = collectionView.frame.height
// Respecting collectionView's ContentInsets properties
width -= (collectionView.contentInset.left + collectionView.contentInset.right)
height -= (collectionView.contentInset.top + collectionView.contentInset.bottom)
if let flowLayout = collectionViewLayout as? UICollectionViewFlowLayout {
// Respecting flowLayout's sectionInset properties
width -= (flowLayout.sectionInset.left + flowLayout.sectionInset.right)
height -= (flowLayout.sectionInset.top + flowLayout.sectionInset.bottom)
// In Vertically scrolling Flow layout
width -= flowLayout.minimumInteritemSpacing
height -= flowLayout.minimumLineSpacing
}
// After considering contentInset and sectionInsets
// we can calculate the width according to
// number of items in single row.
return CGSize(width: width / maximumItemInRow, height: height)
}