How to make the height of a group of a UICollectionView compositional layout equal to the largest UICollectionViewCell in the group?

As you can see in the image below, I have a UICollectionViewCell that contains an UIImageView with a fixed-height image. Below the UIImageView there is a vertical UIStackView that contains all the labels and sub-stackviews with the title, price e.g.

enter image description here

The compositional layout section that results in the image's 2-column grid is this:

func createSection() -> NSCollectionLayoutSection {
    // Layout configuration values
    let cellHeight = CGFloat(205.0)
    let sectionTopSpacing = CGFloat(12.0)
    let sectionLeadingSpacing = CGFloat(12.0)
    let sectionTrailingSpacing = CGFloat(12.0)
    let sectionBottomSpacing = CGFloat(12.0)
    let numberOfColumns = UIDevice.current.userInterfaceIdiom == .pad ? 4 : 2
    let interItemSpacing = CGFloat(8.0)
    let interGroupSpacing = CGFloat(8.0)
    // Item
    let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
                                          heightDimension: .estimated(cellHeight))
    
    let item = NSCollectionLayoutItem(layoutSize: itemSize)
    
    // Group
    let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
                                           heightDimension: .estimated(cellHeight))
    let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize,
                                                   subitem: item,
                                                   count: numberOfColumns)
    group.interItemSpacing = .fixed(interItemSpacing)
    
    // Section
    let section = NSCollectionLayoutSection(group: group)
    section.interGroupSpacing = interGroupSpacing
    section.contentInsets = NSDirectionalEdgeInsets(top: sectionTopSpacing,
                                                    leading: sectionLeadingSpacing,
                                                    bottom: sectionBottomSpacing,
                                                    trailing: sectionTrailingSpacing)
    return section
}

I have tried several compression resistance and hugging priority values both for the vertical stack view and it's labels.

Any idea how I could make the items of the same group have the same height according to the group's tallest item would be more than welcome.

Thank you very much in advance!

Upvotes: 2

Views: 1220

Answers (1)

John Michael
John Michael

Reputation: 1

Man, i've managed it with custom UICollectionViewCompositionalLayout subclass by adjusting the heights to max in layoutAttributesForItem(at indexPath: IndexPath). Also, if you have more than one section you need to adjust y-positions for their items too. For simplicity i will drop this part.

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        let allAttributes = super.layoutAttributesForElements(in: rect)

        return allAttributes?.compactMap { attributes in
            switch attributes.representedElementCategory {
                case .cell:
                    return layoutAttributesForItem(at: attributes.indexPath)

                default:
                    return attributes
            }
        }
    }


    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        let attributes = super.layoutAttributesForItem(at: indexPath)?.copy() as? UICollectionViewLayoutAttributes

        guard let frame = attributes?.frame else {
            return attributes
        }

            if frame.height > maxHeight {
                maxHeight = frame.height
            }
            
            attributes?.frame.size = CGSize(
                width: frame.width,
                height: maxHeight
            )

        return attributes

}


    private var maxHeight = CGFloat.zero

Upvotes: -1

Related Questions