I am trying to implement a collection view, in which items have:
- automatic height based on constraints
- the full available width of the collection view.
I'm aware that this is pretty easy to accomplish UICollectionViewCompositionalLayout
, but I'm looking to solve it for iOS 11+. I've decided to implement a custom UICollectionViewFlowLayout
:
class SingleColumnFlowLayout: UICollectionViewFlowLayout {
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let collectionView = collectionView,
let layoutAttributes = super.layoutAttributesForElements(in: rect) else { return [] }
layoutAttributes
.filter { $0.representedElementCategory == .cell }
.forEach { attributes in
let availableWidth = collectionView.bounds
.inset(by: collectionView.contentInset)
.width
attributes.frame.origin.x = sectionInset.left
attributes.frame.size.width = availableWidth
}
return layoutAttributes
}
}
The result isn't quite what I have imagined:
The cell I'm using is pretty simple:
Interestingly if I add a fixed width constraint to the label, it works correctly, so my theory is that
- for some reason the collection view fails to infer the width of the label correctly
- for that reason, it thinks that it can fit multiple items in the same row
- because of this, it calculates incorrect
y
values for some of the items.
I would like to make this work without fixed-width labels, so my question would be: am I missing anything obvious? Is there a way to fix this?
For anyone interested, I've uploaded the entire project to GitHub.