Swift: different number of cells in string iOS UICollectionView
I want to blend the flow of the UICollectionView layout both vertically and horizontally, I want each row to be divisible by 2 in order to have one item, otherwise it must have a two column grid, I have exhausted every approach, I might think I end up getting one item per line.
The image below is exactly what I want to achieve.
This is what I have tried
class TrendVC: UIViewController {
fileprivate let itemsPerRow: CGFloat = 2
fileprivate let sectionInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
@IBOutlet weak var collectionView: UICollectionView!
var data = [ "others", "sports", "kitchen", "phones", "entertainment", "electronics", "women"]
var dataNames = ["Bags", "Sports & Outdoor", "Kitchen Essentials", "Mobile Phones & Tablets", "Entertainment", "Audio and Video", "Women Clothings"]
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
navigationController?.navigationBar.isTranslucent = true
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
navigationController?.navigationBar.shadowImage = UIImage()
collectionView.dataSource = self
collectionView.delegate = self
collectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
}
extension TrendVC: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item % 3 == 0{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DoubleCell", for: indexPath) as! DoubleTrendCellCell
let datum = data[indexPath.item]
let dat = dataNames[indexPath.item]
cell.trendNameLabel.text = dat
cell.trendImageView.image = UIImage(named: datum)
return cell
}else{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TrendCell", for: indexPath) as! SingleTrendCell
let datum = data[indexPath.item]
let dat = dataNames[indexPath.item]
cell.trendNameLabel.text = dat
cell.trendImageView.image = UIImage(named: datum)
return cell
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.item % 3 == 0{
let paddingSpace = sectionInsets.left * (2 + 1)
let availableWidth = view.frame.width - paddingSpace
let widthPerItem = availableWidth / itemsPerRow
return CGSize(width: widthPerItem, height: widthPerItem)
}
let paddingSpace = sectionInsets.left * (2 + 1)
let availableWidth = view.frame.width - paddingSpace
let widthPerItem = availableWidth / itemsPerRow
return CGSize(width: view.frame.width, height: widthPerItem)
}
//3
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
insetForSectionAt section: Int) -> UIEdgeInsets {
return sectionInsets
}
// 4
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return sectionInsets.left
}
}
This is what I get
source to share
You need to compute modulo 3
instead 2
to get the desired result.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item % 3 == 0{
//return SingleTrendCell
}else{
//return DoubleTrendCellCell
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.item % 3 == 0{
//return SingleTrendCell Size
}
//return DoubleTrendCellCell Size
}
source to share
Since both of your cells have the same structure, it makes no sense to create two different types of cells. All you have to do is use the method sizeForItemAtIndexPath
and return the appropriate dimensions, it autoLayout
will take care of the content inside. Something like:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.item % 3 == 0{
return CGSize(width: collectionView.bounds.size.width/2.0, height: collectionView.bounds.size.height/3.0)
}else{
return CGSize(width: collectionView.bounds.size.width, height: collectionView.bounds.size.height/3.0)
}
}
Note. ... Make sure all your padding and spacing is 0.
source to share