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.

enter image description here

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

enter image description here

+3


source to share


2 answers


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

}

      

+1


source


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.

+1


source







All Articles