Animate frame and layout change of UICollectionView

30,746

Solution 1

I don't have a specific answer, but a few suggestions to consider.

UICollectionView doesn't always handle switching layout instances gracefully. Here is a good discussion of the problem and some workarounds.

But what I’ve actually done in practice that worked for me was to implement both layouts in a single layout object that knows how to toggle between layout modes. I found that switching layout modes in a batch update block was less problematic than using setCollectionViewLayout with two different layout instances:

[self.collectionView performBatchUpdates:^{
    MyLayout *layout = (MyLayout *)self.collectionView.collectionViewLayout;
    layout.mode = otherLayoutMode;
} completion:nil];

Solution 2

First set the grid item size like gridItemSize = CGSizeMake(98, 98); then perform the batch action of UICollectionView. The items in collection view change their sizes with animation. :)

- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout*)collectionViewLayout
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
   return CGSizeMake(gridItemSize.width, gridItemSize.height);
}

[self.collectionview performBatchUpdates:^{
    [self.collectionview.collectionViewLayout invalidateLayout];
    [self.collectionview setCollectionViewLayout:self.collectionview.collectionViewLayout animated:YES];
} completion:^(BOOL finished) {    
}];
Share:
30,746

Related videos on Youtube

Avba
Author by

Avba

Updated on December 27, 2020

Comments

  • Avba
    Avba over 3 years

    I am trying to create an effect where I change the layout of my UICollectionView while changing the frame size

    Initially the collectionView layout presents a "thumbnail" gallery style full screen.

    After resizing the frame to a thin strip - I would like to present a "film strip" style layout

    both layouts independently work fine and as expected.

    I tried code similar to this:

    [UIView animateWithDuration:1
                              delay:0.0
                            options:UIViewAnimationOptionCurveEaseOut
                         animations:^{
                             self.collectionview.frame = newFrame; // animate the frame size
    
    
                         }
                         completion:^(BOOL finished) {
                            [self.collectionView.collectionViewLayout invalidateLayout];
    
        [self.collectionView setCollectionViewLayout:filmstriplayout animated:YES];    // now set the new layout
                         }];
    

    But it is looking very choppy and not resizing as expected.

    Is there a way where I could change the collectionview layout and the frame size simultaneously while animating the change?

    • Benjohn
      Benjohn almost 9 years
      Did you ever get a good solution? performBatchUpdates:withCompletion: is good, but doesn't help with combining an animated frame or contentOffset change. I want to get this for smoothly animating zoom bounce back where my layout and contentOffset dependent on zoom.
    • aheze
      aheze about 3 years
      @Benjohn did you find a good solution? Just came across the same thing and the existing answers aren't ideal...
    • Benjohn
      Benjohn about 3 years
      @aheze Sorry, I don’t know — it’s further back than I can remember now :-/
  • alltom
    alltom about 10 years
    What do you use performBatchUpdates:?
  • Benjohn
    Benjohn almost 9 years
    This is handy stuff, but what about that animated frame change occurring at the same time? Equivalently, I think, a contentOffset change? I also need both to happen at once.
  • marcelosalloum
    marcelosalloum over 4 years
    In my use case, my flowLayout needs to be different when it's being scrolled and when it's static. What I do is: (1st) set a flag in the layout and use the code above to invalidate the layout; (2nd) scrollToIndexPath animated using the default collectionViewMethod; (3rd) reset the layout flag and use the above code again to animate it back to the original state. I couldn't achieve the desired results by animating them at the same time, so I just queued the animations.
  • surfrider
    surfrider about 4 years
    [self.collectionview.collectionViewLayout invalidateLayout]; is odd here, it leads to bugs in animation.
  • Abdul Yasin
    Abdul Yasin over 3 years
    Setting a new instance during an update, seriously?. It will eventually crash your app.