Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resize UICollectionView cells after image inside has been downloaded

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?

like image 895
Fmessina Avatar asked Apr 16 '14 22:04

Fmessina


People also ask

How do I change the size of a cell in collectionView?

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: ...) } }

What is UICollectionViewFlowLayout?

A layout object that organizes items into a grid with optional header and footer views for each section.

How does UICollectionView work?

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.

How do I add a section title in UICollectionView?

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 .


2 Answers

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 */;
}
like image 149
Ash Furrow Avatar answered Oct 17 '22 06:10

Ash Furrow


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.

like image 37
Chris Avatar answered Oct 17 '22 07:10

Chris