GO FURTHER, FASTER: Try the Swift Career Accelerator today! >>

SOLVED: [Swift5/iOS13+/UIKit] UICollectionView & DiffableDataSource & flowLayout: how to add a header?

Forums > iOS

No Storyboard! I have a collectionView with a diffeable datasource. Only one section. I want to display a header, so I registered a custom cell class:

collectionView.register(SectionHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: SectionHeader.reuseidentifier)

I create a flow Layout as such:

    private func createFlexibleFlowLayout(in view: UIView) -> UICollectionViewFlowLayout {
        let width = view.bounds.width
        let padding: CGFloat = 12
        let minimumItemSpacing: CGFloat = 10
        let availableWidth = width - (padding * 2) - (minimumItemSpacing * 2)

        let itemWidth = traitCollection.horizontalSizeClass == .compact ? availableWidth / 2 : availableWidth / 3

        let flowLayout = UICollectionViewFlowLayout()
        flowLayout.sectionInset = UIEdgeInsets(top: padding, left: padding, bottom: padding, right: padding)
        flowLayout.itemSize = CGSize(width: itemWidth, height: itemWidth + 40)

        flowLayout.sectionHeadersPinToVisibleBounds = true

        return flowLayout
    }

The datasource looks as follows:

    func createDataSource() {
        dataSource = UICollectionViewDiffableDataSource<Section, Project>(collectionView: collectionView) { (collectionView, indexPath, project) in
                return self.configure(NormalProjectCell.self, with: project, for: indexPath)
        }

        dataSource?.supplementaryViewProvider = { (collectionView, kind, indexPath) in
            guard let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: SectionHeader.reuseidentifier, for: indexPath) as? SectionHeader else {
                fatalError("Could not dequeue sectionHeader: \(SectionHeader.reuseidentifier)")
            }

            sectionHeader.title.text = "Tap and hold to edit an existing Project!"
            sectionHeader.subtitle.text = "tap to view Project notes"
            return sectionHeader
        }
    }

But how and where do I add the header? The 'old way' doesn't work:

override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {(...)}

I'm stumped!

3      

@emin  

Maybe you are missing the height for that Header?

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        <#code#>
    }

4      

@twostraws  Site AdminHWS+

If you haven't already watched my video on this stuff, you might want to consider doing so: https://www.youtube.com/watch?v=SR7DtcT61tA

4      

@twostraws I have! Excellent video. Had some troubles with the sections so I switched back from compositional layout (I had the headers working there) to flow layout. That's where I can't get the header. But I solved it by doing it differently (no header) ...

3      

Using the SectionHeader class from Paul's video mentioned above I came up with this conversion for your code example. Would this work for you?

private func setupCollectionViewWithCompostionalLayout() {
        // Adjust width and height as needed
        let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.33), heightDimension: .fractionalHeight(0.5))
        let item = NSCollectionLayoutItem(layoutSize: itemSize)

        // Adjust height and item spacing as needed
        let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(60))
        let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
        group.interItemSpacing = .fixed(10)

        let section = NSCollectionLayoutSection(group: group)
        section.contentInsets = NSDirectionalEdgeInsets(top: 12, leading: 12, bottom: 12, trailing: 12)

        // This is where the header gets added:
        let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(50))
        let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: UICollectionView.elementKindSectionHeader, alignment: .top)
        section.boundarySupplementaryItems = [header]

        let layout = UICollectionViewCompositionalLayout(section: section)

        collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView.register(YourCellClassHere.self, forCellWithReuseIdentifier: "cellID")
        collectionView.register(SectionHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: SectionHeader.reuseIdentifier)

        view.addSubview(collectionView)

        NSLayoutConstraint.activate([
            collectionView.topAnchor.constraint(equalTo: view.topAnchor),
            collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
    }

3      

Thanks for taking the effort to sort this out!

3      

Hacking with Swift is sponsored by Essential Developer.

SPONSORED Transform your career with the iOS Lead Essentials. This Black Friday, unlock over 40 hours of expert training, mentorship, and community support to secure your place among the best devs. Click for early access to this limited offer and a free crash course.

Save your spot

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.