Animating UICollectionView on orientation changes
Asked Answered
O

5

15

Consider a UICollectionView that has a different number of items and a different layout (ie: spacing) on landscape and portrait orientation.

What needs to be done for these changes to be animated when the device is rotated? I couldn't find any mention of how to handle rotations on the Collection View Programming Guide.

Odum answered 1/11, 2012 at 16:18 Comment(2)
If you are using flowLayout or a subclass of it, it should automatically reposition the cells for you.If you subclass layout you might need to adjust the layoutattributes you return to correspond to the rotation. The animation should be done for you though.Cryogen
try this https://mcmap.net/q/821559/-uicollectionview-animation-custom-layoutMouthy
T
40

It's not necessary to reload the collection view's data — invoking [collectionView.collectionViewLayout invalidateLayout] will cause the collection view to update its layout.

Overriding shouldInvalidateLayoutForBoundsChange: to return YES in a UICollectionViewLayout subclass will result in invalidateLayout being called automatically whenever the collection view's bounds change (including when its size changes and when the user scrolls its contents).

Tektite answered 7/8, 2013 at 16:48 Comment(0)
W
13

I had different number of sections based on the orientation, and the auto rotation didn't change it. I had to add a call to the collectionView to reload the data. I'm using a UICollectionViewController, adjust to your own collection view property if you have something else:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(    NSTimeInterval)duration {
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
    [self.collectionView reloadData];
}
Woodie answered 17/12, 2012 at 3:50 Comment(0)
R
6

The quickest way is a mix of all other answers.

just add the following lines in your ViewController :

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

You do not need to reloadData.

Rozier answered 20/1, 2016 at 14:43 Comment(0)
H
3

I used the following simple code in Swift:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
    collectionView.collectionViewLayout.invalidateLayout()
}
Hearts answered 3/10, 2016 at 18:15 Comment(1)
Note that this will crash randomly. Reference: #57750615Agenda
C
0

I am using this approach if you only want to do something at a rotation event:

- (void)updateViewConstraints {
    [super updateViewConstraints];
    [[_cvMyCollectionView collectionViewLayout] invalidateLayout];
}

and then override the method from UICollectionViewDelegateFlowLayout

    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
        /* 
         * Calculate size, example
         * */
         CGSize cellSize = CGSizeMake(150.0f, 150.0f);

      return cellSize;
      }

with the desired behaviour in landscape and portrait or depending on the width for example.

You can even save previous orientation and check if it changed to decide whether to invalidate layout or not.

This will refresh sizes even when you come back again in a navigation controller.

Contractor answered 6/5, 2015 at 11:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.