PrepareFor
PrepareFor

Reputation: 2598

How to deal with empty items section in UICollectionView CompositionalLayout

I'm trying to make collection view with compositional layout which have multi sections

but if there is empty items in sections how can I deal with it?

if item is empty I don't want to show that section

UICollectionViewCompositionalLayout { (section, env) -> NSCollectionLayoutSection? in
  // do I have to code in this area? 
}

enter image description here

Upvotes: 4

Views: 2481

Answers (3)

Andrey Isaev
Andrey Isaev

Reputation: 192

I have faced the same problem recently. Since I have just 3 or 2 sections I added layout with 2 sections dedicated for the empty case, and switch between them when updating data source.

Upvotes: 0

orbitekk
orbitekk

Reputation: 21

I had the same problem and I fixed it like this:

import UIKit

final class CollectionViewCompositionalLayout: UICollectionViewCompositionalLayout {
    override init(sectionProvider: @escaping UICollectionViewCompositionalLayoutSectionProvider) {
        weak var weakSelf: CollectionViewCompositionalLayout?

        super.init { section, environment in
            guard
                let strongSelf = weakSelf,
                let collectionView = strongSelf.collectionView,
                let dataSource = collectionView.dataSource,
                dataSource.collectionView(collectionView, numberOfItemsInSection: section) == 0
            else {
                return sectionProvider(section, environment)
            }
            return strongSelf.emptySectionLayout()
        }

        weakSelf = self
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

extension CollectionViewCompositionalLayout {
    private enum Constants {
        static let size: CGFloat = 0.1
    }

    private func emptySectionLayout() -> NSCollectionLayoutSection {
        let size = NSCollectionLayoutSize(
            widthDimension: .estimated(Constants.size),
            heightDimension: .estimated(Constants.size)
        )
        let item = NSCollectionLayoutItem(
            layoutSize: size
        )
        let group = NSCollectionLayoutGroup.vertical(
            layoutSize: size,
            subitems: [item]
        )
        let emptySectionLayout = NSCollectionLayoutSection(group: group)
        return emptySectionLayout
    }
}

It doesn't look good but works pretty well :)

Upvotes: 1

Viktor Gavrilov
Viktor Gavrilov

Reputation: 976

If you are also using UICollectionViewDiffableDataSource, you could deal with empty sections when you are creating/updating your snapshots - append only sections with items in it.

In my project I do something like this:

func performQuery(animate: Bool) {
    var currentSnapshot = NSDiffableDataSourceSnapshot<Section, ViewCell>()
    
    if !calendars.isEmpty {
        currentSnapshot.appendSections([Section(name: "main")])
        currentSnapshot.appendItems(calendars, toSection: Section(name: "main"))
    }

    if !lifeCals.isEmpty {
        currentSnapshot.appendSections([Section(name: "life")])
        currentSnapshot.appendItems(lifeCals, toSection: Section(name: "life"))
    }
    
    dataSource.apply(currentSnapshot, animatingDifferences: animate)
}

This way in case user has 0 life calendars, there will be no "life" section.

Upvotes: 2

Related Questions