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?
Here's a WWDC video demoing this technique. class MyLayout: UICollectionViewFlowLayout { override func prepare() { super. prepare() guard let collectionView = collectionView else { return } itemSize = CGSize(width: ..., height: ...) } }
A layout object that organizes items into a grid with optional header and footer views for each section.
From apple's documentation, UICollectionView is: An object that manages an ordered collection of data items and presents them using customizable layouts. The name and definition makes it clear, it is a way to display a Collection of UI Views in our app. The individual view is referred as a Cell.
There are no section headers in the UICollectionView. So for your first task, you'll add a new section header using the search text as the section title. To display this section header, you'll use UICollectionReusableView .
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 */;
}
To resize collection view cells, you could reload the collection view and return the size of you collection view cells dynamically in the method:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
return [cell size];
}
In cases when the cell's size is dynamic, get the cell from the index path and return its size based on the size of the image. I usually create a method for the cell to return a dynamic size, like in the example above. You can use UIImage's size property to help return the size based on the image.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With