Spacemonkey
Spacemonkey

Reputation: 1763

Sections with different cell size with UICollectionView

I have to create a view in a Swift project with two differentiate sections. The first one has seven cells with square shape. The second one has three cells with rectangular shape. Data inside cells are static. In all cases, the sections should fit the entire screen width (mostly in landscape mode).

I don't have much experience using UICollectionViewController so I decided to accomplish this using one UICollectionViewController class and two reusable cells, but when I set the first section cell width the second one is also affected and then cells width is cut.

Is my point correct? Shall I use different UICollectionViewControllers (one per section)?

Update: My Controller code

import UIKit

class InverterController: UICollectionViewController, UICollectionViewDelegateFlowLayout {

    let moduleCell = "moduleCell"
    let parameterCell = "parameterCell"

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        if section > 0 {
            return CGSizeZero
        } else {
            return CGSize(width: collectionView.frame.width, height: CGFloat(195))
        }
    }

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtPath indexPath: NSIndexPath) -> CGSize {

        var newSize = CGSizeZero

        if indexPath.section == 0 {

            newSize =  CGSizeMake(CGFloat(105), CGFloat(105))
        } else {
            newSize = CGSizeMake(CGFloat(313), CGFloat(200))
        }

        return newSize
    }

    override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
        switch kind {
            case UICollectionElementKindSectionHeader:
                let headerView = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "inverterHeader", forIndexPath: indexPath)
                return headerView
            default:
                assert(false, "Unexpected element kind")
        }
    }

    /**
     Two sections in this UICollectionView: First one for clock items, second one for other parameters.
     */
    override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 2
    }

    /**
     First section contains one cell
     Second section contains three cells
     */
    override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        var items = 0

        if section == 0 {
            items = 7
        } else {
            items = 3
        }

        return items
    }

    override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

        var cellIdentifier = ""

        if indexPath.section == 0 {
            cellIdentifier = moduleCell
        } else {
            cellIdentifier = parameterCell
        }

        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(cellIdentifier, forIndexPath: indexPath)
        cell.layer.cornerRadius = 6
        cell.layer.masksToBounds = true

        return cell
    }
}

Interface Builder configuration for CollectionView enter image description here

Simulator screenshot (non desired result; all cells have the same width) enter image description here

Upvotes: 7

Views: 8732

Answers (2)

Yunus Tek
Yunus Tek

Reputation: 626

for Swift 4

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

    let width : CGFloat
    let height : CGFloat

    if indexPath.section == 0 {
        // First section
        width = collectionView.frame.width/7
        height = 50
        return CGSize(width: width, height: height)
    } else {
        // Second section
        width = collectionView.frame.width/3
        height = 50
        return CGSize(width: width, height: height)
    }
}

func collectionView(_ collectionView: UICollectionView,
                layout collectionViewLayout: UICollectionViewLayout,
                minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return 1.0
}

func collectionView(_ collectionView: UICollectionView, layout
    collectionViewLayout: UICollectionViewLayout,
                    minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 1.0
}

Upvotes: 0

Swifty
Swifty

Reputation: 3760

You can use collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize delegate method to adjust cell size.

In your case you could write something like this:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {

    let width : CGFloat
    let height : CGFloat

    if indexPath.section == 0 {
        // First section
        width = collectionView.frame.width/7
        height = 50
        return CGSizeMake(width, height)
    } else {
        // Second section
        width = collectionView.frame.width/3
        height = 50
        return CGSizeMake(width, height)
    }

}

Put this code inside your collectionViewController class.
Set height to what your cell height should be. You might want to adjust width if you're using spacing between cells or insets in your collectionView.

Upvotes: 6

Related Questions