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!
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()
}
To have the collection view resize its cells, and have the change animated during rotation, use the transition coordinator:
(Swift 4+)
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
// Have the collection view re-layout its cells.
coordinator.animate(
alongsideTransition: { _ in self.collectionView.collectionViewLayout.invalidateLayout() },
completion: { _ in }
)
}
You might use viewWillLayoutSubviews
. This question should be helpful but this is bassically called whenever the view controller views is about to layout its subviews.
So your code will look like this:
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
guard let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else {
return
}
if UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication().statusBarOrientation) {
//here you can do the logic for the cell size if phone is in landscape
} else {
//logic if not landscape
}
flowLayout.invalidateLayout()
}
I've tended to use viewWillTransitionToSize
with the same thing and simply made a call invalidateLayout()
in there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With