Skip to content

Instantly share code, notes, and snippets.

@chenr2
Last active February 18, 2019 11:08
Show Gist options
  • Save chenr2/2132e51ff9b77688ec94 to your computer and use it in GitHub Desktop.
Save chenr2/2132e51ff9b77688ec94 to your computer and use it in GitHub Desktop.
Swift: Handle rotation for UICollectionView cell sizes

Handle rotation for UICollectionView cell sizes

Requires iOS 8+

Say you want 3 cells per row in portrait, but 4 cells in landscape. First calculate the cell dimensions based on the screen width and a padding of 5.

var cellsPerRow:CGFloat = 3
let cellPadding:CGFloat = 5

extension ViewController : UICollectionViewDelegateFlowLayout {
    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
        let widthMinusPadding = UIScreen.mainScreen().bounds.width - (cellPadding + cellPadding * cellsPerRow)
        let eachSide = widthMinusPadding / cellsPerRow
        return CGSize(width: eachSide, height: eachSide)
    }
}

The above assumes you set Min Spacing and Section Insets values all to 5 in the Storyboard.

traitCollectionDidChange gets called on rotation. On iPhone, verticalSizeClass changes from .Regular (portrait) to .Compact (landscape). Don't bother checking horizontalSizeClass because it's always .Compact.

    override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
        cellsPerRow = (traitCollection.verticalSizeClass == .Compact) ? 4 : 3
        collectionView.reloadData()
    }
@evil159
Copy link

evil159 commented Feb 18, 2019

traitCollectionDidChange(previousTraitCollection :) won't be called on iPad when it is rotated, because size class is .regular in both portrait and landscape orientations. There's viewWillTransition(to:with:) that will be called whenever collection view size changes.

Also you shouldn't use UIScreen.mainScreen().bounds if your app supports multitasking as it might not occupy the whole screen, better use collectionView.frame.width for that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment