Resize UICollectionView cells after image inside has been downloaded

Fmessina picture Fmessina · Apr 17, 2014 · Viewed 15.1k times · Source

I'm building a UICollectionView and my custom cells will contain two labels and one image.

Each image is downloaded asynchronously so I don't know it's size until the download it's complete. Once is downloaded, I want to adapt each cell to re-layout it's content and frame to fit in height the image just downloaded.

As UICollectionViewLayout, I'm using CHTCollectionViewWaterfallLayout

To download the image asynchronously I'm using SDWebImage, like this:

    [cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
                   placeholderImage:[UIImage imageNamed:@"placeholder.png"]
                          completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) 
                                {... some completion code here ...}];

QUESTION:

What is the right approach to resize each UICollectionViewCell right after the image is downloaded?

Answer

Ash Furrow picture Ash Furrow · Apr 22, 2014

You should just be able to invalidate your collection view layout in an animation block when the image comes back. Things might get a little complicated if more than one image finishes completion at once, but this should work:

[cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
               placeholderImage:[UIImage imageNamed:@"placeholder.png"]
                      completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType)^{
                          [UIView animateWithDuration:0.3f animations:^{
                              [self.collectionView.collectionViewLayout invalidateLayout];
                          }];
                      }];

Then just return a different size in the appropriate delegate method.

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    return /* a different size if the image is done downloading yet */;
}