UICollectionView Custom Layout Tutorial: Pinterest | raywenderlich.com

Build a UICollectionView custom layout inspired by the Pinterest app, and learn how to cache attributes and dynamically size cells.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/4829472-uicollectionview-custom-layout-tutorial-pinterest

In the https://www.raywenderlich.com/3987-custom-collection-view-layout course, the instructor computed the image height for the bounding box preserving the aspect ratio as follows:

func collectionView(_ collectionView: UICollectionView, heightForImageAtIndexPath indexPath: IndexPath, withWidth width: CGFloat) -> CGFloat {
    
    let character = charactersData[indexPath.item]
    let image = UIImage(named: character.name)
    let boundingRect = CGRect(x: 0, y: 0, width: width, height: CGFloat(MAXFLOAT))
    let rect = AVMakeRect(aspectRatio: image!.size, insideRect: boundingRect)
    
    return rect.height
  }

The text height also was computed as:

func collectionView(_ collectionView: UICollectionView, heightForDescriptionAtIndexPath indexPath: IndexPath, withWidth width: CGFloat) -> CGFloat {
    let character = charactersData[indexPath.item]
    let descriptionHeight = heightForText(character.description, width: width-24)
    let height = 4 + 17 + 4 + descriptionHeight + 12
    return height
  }
  
  func heightForText(_ text: String, width: CGFloat) -> CGFloat {
    let font = UIFont.systemFont(ofSize: 10)
    let rect = NSString(string: text).boundingRect(with: CGSize(width: width, height: CGFloat(MAXFLOAT)), options: .usesLineFragmentOrigin, attributes: convertToOptionalNSAttributedStringKeyDictionary([convertFromNSAttributedStringKey(NSAttributedString.Key.font): font]), context: nil)
    return ceil(rect.height)
  }
}

The PinterestLayout doesn’t utilize any of this. It also doesn’t seem to add the text height to the height of the cell height. However, it doesn’t seem to make a difference for this for some reason.

What makes the PinterestLayout still work without these proper computations? I removed the padding heights in the cell height computation for PinterestLayout and it still worked without anything overlapping or being clipped.

It confused me, too. Do you know why?

@haawa Can you please help with this when you get a chance? Thank you - much appreciated! :]

How to handle pagination with this layout. I am not able to reloaddata.

Hi Team. Thanks for the tutorial. I am able to display static images with the custom flow layout.

What if images are coming from server?

func collectionView(_ collectionView: UICollectionView, heightForPhotoAtIndexPath indexPath: IndexPath) → CGFloat is not getting called when we reloadthecollection. Can you please look into this and do needful.

Thanks,
Ram

Honestly I am a bit baffled by the lack of text computation for size.
EDIT
I worked out the answer, I think.
It seems that the overall height of the cell is the actual height of the image, e.g. 320 points for image 01, however the image view actually only takes 254 points in height inside the view itself. So the image is invariably resized DOWN, the text ALWAYS shows up because it uses dynamic layout within the pre-allocated height.
ALSO NOTE: The layout isn’t invalidated upon rotation

@haawa Do you have any feedback about this? Thank you - much appreciated! :]

I faced the same problem. I just remove the “cache.isEmpty” in the “guard” verification and I clear the cache before the “for in”. Hope it helps you.

@diogeeenis Thank you for sharing your solution - much appreciated! :]

This tutorial is more than six months old so questions are no longer supported at the moment for it. Thank you!