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.
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