I want to show images of different dimensions (800x600, 800x800, 800x1200 etc) in a collection view (each image is one cell). The width of the cell is static and equal to the width of the collection view, but the height needs to be dynamic, calculated based on the displayed image, so that we never crop any artwork!
I am using UICollectionViewCompositionalLayout
and load cells from dedicated nibs like this:
collectionView.register(UINib(nibName: "Image", bundle: nil), forCellWithReuseIdentifier: "ImageCell")
and then
private func cell(collectionView: UICollectionView, indexPath: IndexPath, item: Item) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell...
cell.setup(...)
return cell
}
The ImageCell
only has one image view constrained to its superview (the cell's contentView
):
The layout for this cell is using an .estimated
height:
private func createImageSectionLayout() -> NSCollectionLayoutSection {
let item = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(20)))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(20)), subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.interGroupSpacing = 16
section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 16, bottom: 16, trailing: 16)
return section
}
Finally, I'm using ScaledHeightImageView
, a UIImageView
subclass that calculates the intrinsic size based on its image's aspect ratio (taken from here).
Now the problem is that when I setup the cell and calculate the intrinsic size, the imageView's width is the one from the storyboard, and not the one from the parent UICollectionView
, so my cell's height is always wrong.
Can someone help me understand what is wrong with my setup?
I have tried to experiment with:
- setting up the cell in
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath)
- overriding
layoutSubviews()
in theUICollectionViewCell
subclass - calling
layoutIfNeeded()
from several places
but nothing seems to work.