Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resizing UICollectionViewCells on rotation changes currently visible cells [duplicate]

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:

Before Rotation

After 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)
}
like image 606
JAL Avatar asked Jul 15 '16 18:07

JAL


Video Answer


1 Answers

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)
}
like image 89
Evgeny Karkan Avatar answered Sep 30 '22 15:09

Evgeny Karkan