11

I am able to achieve UICollectionView with dynamic height cell, as shown in the following screenshot. Height of the cell will be automatically adjusted based on content.

enter image description here

Here's is the code to achieve such outcome.

private func updateListLayout() {
    // Item
    let itemSize = NSCollectionLayoutSize(
        widthDimension: .fractionalWidth(1.0),
        heightDimension: .estimated(1)
    )
    let item = NSCollectionLayoutItem(layoutSize: itemSize)
    item.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)
    
    // Group
    let groupSize = itemSize
    //let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
    let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: 1)
    group.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)
    group.interItemSpacing = .fixed(0)
    
    let section = NSCollectionLayoutSection(group: group)
    // Spacing for collection view's leading & trailing & bottom. For top, it is the spacing between header and item
    section.contentInsets = NSDirectionalEdgeInsets(
        top: DashboardViewController.padding * 2,
        leading: DashboardViewController.padding,
        bottom: DashboardViewController.padding * 2,
        trailing: DashboardViewController.padding
    )
    // Vertical spacing between cards within different group.
    section.interGroupSpacing = DashboardViewController.padding
    
    let headerFooterSize = NSCollectionLayoutSize(
        widthDimension: .fractionalWidth(1.0),
        heightDimension: .estimated(1)
    )
    let sectionHeader = NSCollectionLayoutBoundarySupplementaryItem(
        layoutSize: headerFooterSize,
        elementKind: UICollectionView.elementKindSectionHeader,
        alignment: .top
    )
    section.boundarySupplementaryItems = [sectionHeader]
    
    let compositionalLayout = UICollectionViewCompositionalLayout(section: section)

    // Switch the layout to UICollectionViewCompositionalLayout
    collectionView.collectionViewLayout = compositionalLayout
}

We notice that by using

heightDimension: .estimated(1)

will yield poor performance. It took 2 to 3 seconds, to switch the page tab successfully.

If we change the heightDimension to a higher estimated value, that will increase the performance significantly. It took less than 1 second, to switch the page tab successfully.

heightDimension: .estimated(400)

However, that comes with the following side-effect. Some cards will randomly have an overshot height effect as shown below.

enter image description here

Within a card, we have value 1000 Vertical Content Hugging Priority for the bottom subview. But as you can see in the screenshot, bottom view still try to grow itself to fill up the overshot height.


Our problem right now is

  1. If we are using .estimated(1) for height, we will get correct dynamic height behavior. But, that comes with cost of poor runtime performance.
  2. If we provide a large enough value like .estimated(400) for height, we will get a good runtime performance. However, some card can randomly get an overshoot height effect.

Do anyone know the right way, to achieve UICollectionView with correct dynamic cell height, without impacting runtime performance?

Cheok Yan Cheng
  • 47,586
  • 132
  • 466
  • 875
  • May be old post but this may help you : [How to set UICollectionViewCell width and heigh programmatically](https://stackoverflow.com/questions/38028013/how-to-set-uicollectionviewcell-width-and-height-programmatically) – Ptit Xav Sep 09 '21 at 15:30
  • Could you provide the code used for your cells? – GaétanZ Sep 13 '21 at 11:09
  • And what about a value in between? Like `.estimated(100)` ? – GaétanZ Sep 13 '21 at 11:10
  • Why your group is `NSCollectionLayoutGroup.horizontal` as it seems to be `vertical`? Try it and use estimated value to minimal assumed height (instead of 1), because it is used as *default initial* value. – Asperi Sep 14 '21 at 17:08
  • 1
    Using NSCollectionLayoutGroup.horizontal is a right way, as the `count: 1` is always 1, so that 1 cell will fully expand the width. – Cheok Yan Cheng Sep 15 '21 at 05:14

0 Answers0