iosswiftuicollectionviewautolayoutuicollectionviewcompositionallayout

Collection view self-sizing cells issue in Compositional layout


I am using a collection view compositional layout to display a cell with two labels that can grow in height, depending on the content of the labels. Everything else in the cell is fixed.
I make a section like this:

let item = NSCollectionLayoutItem(
            layoutSize: NSCollectionLayoutSize(
                widthDimension: .fractionalWidth(1),
                heightDimension: .fractionalHeight(1)))

let group = NSCollectionLayoutGroup.vertical(
            layoutSize: NSCollectionLayoutSize(
                widthDimension: .fractionalWidth(1),
                heightDimension: .estimated(300)),
            subitems: [item])

let section = NSCollectionLayoutSection(group: group)

The problem is, it's either too big, or too small, but the correct height is never being calculated. My assumption is that this is due to the fact that I am setting the text for the label inside a configure method but not during the cell initialization.

let cell = collectionView.dequeueReusableCell(
                reusableCell: MyCustomCell.self,
                indexPath: indexPath)
cell.configure(viewModel: viewModel)

Any ideas how I can fix it? I tried invalidating the layout or reloading the data to re-calculate the height, but it didn't help.


Solution

  • Since the labels live on the item and the item is the one that sizes the group, you need to have an .estimated height dimension on your item and if you only plan on having one item per group then the heigh dimension of the group would be the same as the item. So in this case both the item and the group should have .estimated(300). Your current code is basically saying: Make the item as tall as the group which we estimate is 300pt tall but then the group has no way to know it's height and thus you end up with the wrong layout. Generally you want to only use fractional dimensions for items nested in groups with absolute or fractional dimensions (along a given axis) to avoid this.