Scott Scott - 3 months ago 25
iOS Question

UICollectionView dynamic custom layout

i'm trying to create a UICollectionView with the type of layout as the image I've attached. And i'm a little confused as to how to achieve this layout.

After doing some googling it seems like I need to write a custom UICollectionViewFlowLayout, but I can't seem to find any examples of layouts that have different section counts per item.

if you look at the mockup the first item has one section. The image is Landscape, but the middle item has 2 sections with 2 portrait images.

Am I looking into the wrong thing? could someone point me in the right direction?

Layout Mockup

Answer

You can do this using UICollectionViewDelegateFlowLayout, no need to subclass.

Here is an example:

import UIKit

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {

    @IBOutlet weak var collectionView: UICollectionView!

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

    // MARK: - UICollectionViewDataSource

    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 1
    }

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("TestCollectionViewCell", forIndexPath: indexPath) as! UICollectionViewCell
        if indexPath.item % 3 == 0 {
            cell.backgroundColor = UIColor.redColor()
        } else {
            cell.backgroundColor = UIColor.greenColor()
        }
        return cell
    }

    // MARK: - UICollectionViewDelegateFlowLayout

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
        let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
        if indexPath.item % 3 == 0 {
            let cellWidth = (CGRectGetWidth(collectionView.frame) - (flowLayout.sectionInset.left + flowLayout.sectionInset.right))
            return CGSize(width: cellWidth, height: cellWidth / 2)
        } else {
            let cellWidth = (CGRectGetWidth(collectionView.frame) - (flowLayout.sectionInset.left + flowLayout.sectionInset.right) - flowLayout.minimumInteritemSpacing) / 2
            return CGSize(width: cellWidth, height: cellWidth)
        }
    }

}