4

I need to create a UICollectionView cells with dynamic heights according to each cell's image view height. I have created a subclass from UICollectionViewFlowLayout to implement the desired behaviour as follows:

#define numColumns 2

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {

    NSArray* attributesToReturn = [super layoutAttributesForElementsInRect:rect];

    for (UICollectionViewLayoutAttributes* attributes in attributesToReturn) {

        if (attributes.representedElementKind == nil) {

            NSIndexPath* indexPath = attributes.indexPath;
            attributes.frame = [self layoutAttributesForItemAtIndexPath:indexPath].frame;

        }

    }

   return attributesToReturn;

}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {

    UICollectionViewLayoutAttributes* currentItemAttributes = [super layoutAttributesForItemAtIndexPath:indexPath];

    if (indexPath.item < numColumns) {

        CGRect frame = currentItemAttributes.frame;
        frame.origin.y = 5;
        currentItemAttributes.frame = frame;

        return currentItemAttributes;

    }

    NSIndexPath* indexPathPrev = [NSIndexPath indexPathForItem:indexPath.item-numColumns inSection:indexPath.section];
    CGRect framePrev = [self layoutAttributesForItemAtIndexPath:indexPathPrev].frame;
    CGFloat YPointNew = framePrev.origin.y + framePrev.size.height + 10;
    CGRect frame = currentItemAttributes.frame;
    frame.origin.y = YPointNew;
    currentItemAttributes.frame = frame;

    return currentItemAttributes;

}

And in the collection view controller delegate flow layout

 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {

    float imageHeight = [[(Product *)self.products[indexPath.row] image] height];
    float imageWidth = [[(Product *)self.products[indexPath.row] image] width];

    float ratio = 150.0/imageWidth;

    return CGSizeMake(150, ratio*imageHeight);

}

Cell implementation

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    ProductCell *cell = (ProductCell *)[self.collectionView dequeueReusableCellWithReuseIdentifier:@"ProductCell" forIndexPath:indexPath];

    ....

    [cell.imageView setImageWithURL:[NSURL URLWithString:[[(Product *)self.products[indexPath.row] image] url]]];

    return cell;

}

All the cells showed up as expected, but the content view was too long as shown.

Dynamic UICollectionView height

I think I have to implement the method -(CGSize)collectionViewContentSize to get the correct contentSize, but I don't know how to calculate the actual height of the collection view

Mohamed Salem
  • 161
  • 3
  • 8
  • You're right about overriding `collectionViewContentSize`. The trouble is that `collectionViewContentSize` is called before the other methods you've already overridden. Perhaps in `prepareLayout` you can pre-calculate your layout by interfacing with the `datasource` of the `UIScrollView`. Can you post more code, perhaps how `numColumns` is calculated, or where the cells come from? – Gutblender Aug 23 '14 at 02:56
  • numColumns is a defined constant equals 2, and cells come from a custom collection view cell named ProductCell. Cells are populated with variable height images retrieved from a web service. – Mohamed Salem Aug 23 '14 at 10:29
  • More code posted for clarification – Mohamed Salem Aug 23 '14 at 10:48
  • The best I can suggest is, when you get these variable heights, to save the maximum "lowest edge" via `bottomEdge = frame.origin.y + frame.size.y` when you have access to all the cell frames. – Gutblender Aug 23 '14 at 18:36
  • Or perhaps request the images in `prepareLayout`, save them in RAM, and calculate the maximum bottom edge across the two columns. You can still assign the images later, I would expect. – Gutblender Aug 23 '14 at 18:47
  • Hi, I'm working on this issue, but I keep getting zero with in the rect of layoutAttributesForElementsInRect. Any idea? – Cristian Pena Feb 24 '15 at 21:59
  • I ended up using this layout instead https://github.com/chiahsien/CHTCollectionViewWaterfallLayout – Mohamed Salem Feb 26 '15 at 13:24
  • @MohamedSalem I'm also running into the same problem. How were you able to scale down the images and obtain the correct size for 'sizeForItemAtIndexPath' method? – user805981 Jun 16 '15 at 17:35

0 Answers0