Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UICollectionView with self-sizing cells resizes cells during insert/remove animation

I have a simple UICollectionView with a UICollectionViewFlowLayout that uses autolayout to allow for self-sizing cells. Things work great in a static layout, but when I insert or remove cells, the cells resize to the estimated size:

[self.collectionView performBatchUpdates:^{
    [self.collectionView insertItemsAtIndexPaths:@[indexPath]];
} completion:nil];

Beyond setting the estimated size, like this:

layout.estimatedItemSize = CGSizeMake(88.0, 88.0);

I'm not doing anything fancy in the collection view. Everything is set up using storyboards.

How can I avoid this resizing? I'm only targeting iOS 8.0 and up so it should be supported.

example of the problem

like image 881
Senior Avatar asked Sep 09 '25 23:09

Senior


2 Answers

I ran into this, and it took me a while to figure out that the size it was reverting to was the estimated size.

I think I figured out a workaround:

  • Keep one instance of your self-sizing cell class around
  • Implement sizeForItemAtIndexPath, and configure that cell instance with data for that index path, then ask it for its preferred size (systemLayoutFittingSize).
  • Cache this information in a dictionary for performance.

See example project here.

like image 78
Tom Hamming Avatar answered Sep 12 '25 13:09

Tom Hamming


  1. Set estimatedItemSize property to some appropriate size.

  2. In your custom UICollectionView class override below method and cache layoutAttributes's size given by super.

    -(UICollectionViewLayoutAttributes*)preferredLayoutAttributesFittingAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes
    {
        UICollectionViewLayoutAttributes * superAttr = [super preferredLayoutAttributesFittingAttributes:layoutAttributes];
       //Cache size which is returned by super (superAttr.frame.size) since super calculates the correct size for auto size cells.
        return superAttr;
    }
    

3.In sizeForItemAtIndexPath return cached size if available else estimated size.

-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 
{
    //return cached size if available else the estimated size
}
like image 32
dev gr Avatar answered Sep 12 '25 12:09

dev gr