UICollectionView - resizing cells on device rotate - Swift

Ben picture Ben · Dec 7, 2015 · Viewed 38.5k times · Source

I've created a UICollectionView, so that I can arrange views into neat columns. I'd like there to be a single column on devices > 500 pixels wide.

In order to achieve this, I created this function:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    let size = collectionView.frame.width
    if (size > 500) {
        return CGSize(width: (size/2) - 8, height: (size/2) - 8)
    }
    return CGSize(width: size, height: size)
}

This works as expected on first load, however when I rotate the device, the calculation doesn't always happen again, and the views don't always redraw as expected. Here's my code for when the device is rotated:

override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
    collectionView.collectionViewLayout.invalidateLayout()
    self.view.setNeedsDisplay()
}

I'm assuming I've forgotten to redraw something, but I'm not sure what. Any ideas are very gratefully recieved!

Answer

valvoline picture valvoline · Mar 15, 2017

Perhaps the most straight way to make this is to invalidateLayout during the viewWillTransitionToSize:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    guard let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else {
        return
    }
    flowLayout.invalidateLayout()
}