2

I would like to make a list layout with Grouped Rounded Rect style using UICollectionViewCompositionalLayout. Am not able to get the background Decoration item applied to the section header.

Using NSCollectionLayoutDecorationItem, I was able to get the RoundedRect style, and grouped style using insetGroup appearance in configuration.

func listSection(withEstimatedHeight estimatedHeight: CGFloat = 100, environment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection {
        
        var config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
        config.headerMode = .supplementary
        config.showsSeparators = false
        
        let section = NSCollectionLayoutSection.list(using: config, layoutEnvironment: environment)
        
        section.decorationItems = [
            NSCollectionLayoutDecorationItem.background(elementKind: "BackgroundView")
        ]
        
        let layoutSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(44.0))
        let sectionHeader = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: layoutSize, elementKind: UICollectionView.elementKindSectionHeader, alignment: .top)
        section.boundarySupplementaryItems = [sectionHeader]
        
        return section
    }

However, when I add the sectionHeader, the rounded rect background seem to have no effect on the header.

Sample output

I would like the rounded rect to be applied to the entire section including header.

Friendtam
  • 311
  • 4
  • 11

1 Answers1

0

Background decoration view is on the same level of hierarchy as collection view cells and boundary supplementary items. That's why it's not possible to clip section content to the background decoration view.

The only way I've been able to overcome this issue is to round header's top left and top right corners separately.

extension UIView {
    func setRoundCorners(corners: UIRectCorner, radius: CGFloat) {
        self.clipsToBounds = true
        self.layer.cornerRadius = radius
        var masked = CACornerMask()
        if corners.contains(.topLeft) { masked.insert(.layerMinXMinYCorner) }
        if corners.contains(.topRight) { masked.insert(.layerMaxXMinYCorner) }
        if corners.contains(.bottomLeft) { masked.insert(.layerMinXMaxYCorner) }
        if corners.contains(.bottomRight) { masked.insert(.layerMaxXMaxYCorner) }
        
        if corners.contains(.allCorners) {
            masked = [.layerMinXMinYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMaxYCorner]
        }
        self.layer.maskedCorners = masked
    }
}

And then in the setup function of your CollectionViewHeader class:

final class CollectionViewHeaderView: UICollectionReusableView {
    override func awakeFromNib() {
        super.awakeFromNib()
    
        setup()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
    
        setup()
    } 

    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
}

// MARK: - Private functions
private extension CollectionViewHeaderView {
    func setup() {
        self.setRoundCorners(corners: [.topLeft, .topRight], radius: 16)
    }
}
Hopreeeenjust
  • 257
  • 4
  • 5