I have a paginated, horizontally scrolling UICollectionView
where each cell takes up the size of the view/device screen, and one cell appears at a time. I'm experiencing an issue where on device rotation, the cells will transition to the correct new size, but the position of the cells will be off.
Before Rotation:
After Rotation:
On rotation, how can I not only resize the collection view cells properly but ensure that the current cell stays visible?
I've boiled this problem down to a very simple example without a custom flow layout.
Setting the size of the cells to the collectionView
frame's size (the collection view is the size of the view controller holding it):
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return collectionView.frame.size
}
Attempting to handle rotation in viewWillLayoutSubviews
:
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
guard let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else { return }
flowLayout.itemSize = collectionView.frame.size
flowLayout.invalidateLayout()
}
Actually, if I call invalidateLayout()
in viewWillLayoutSubviews
, setting the itemSize
here shouldn't be necessary, as sizeForItemAtIndexPath
will be called when the layout is recreated.
I've also tried manually scrolling to the first visible cell during rotation after setting the new itemSize, but that shows no improvement:
if let item = collectionView.indexPathsForVisibleItems().first {
collectionView.scrollToItemAtIndexPath(item, atScrollPosition: .CenteredHorizontally, animated: true)
}
You should handle content offset of your UICollectionView
, so in your view controller try to override viewWillTransitionToSize
function from UIContentContainer
protocol, like this:
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
let offset = yourCollectionView?.contentOffset;
let width = yourCollectionView?.bounds.size.width;
let index = round(offset!.x / width!);
let newOffset = CGPointMake(index * size.width, offset!.y);
yourCollectionView?.setContentOffset(newOffset, animated: false)
coordinator.animateAlongsideTransition({ (context) in
yourCollectionView?.reloadData()
yourCollectionView?.setContentOffset(newOffset, animated: false)
}, completion: nil)
}
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