Add badge (supplementary view) to UICollectionLayoutListConfiguration

Viewed 365

Is there any way to add a badge NSCollectionLayoutSupplementaryItem) to a UICollectionLayoutListConfiguration?

I'm trying to implement a sidebar using Modern Collection Views:

var configuration = UICollectionLayoutListConfiguration(appearance: .sidebar)
...

let section = NSCollectionLayoutSection.list(using: configuration, layoutEnvironment: layoutEnvironment)

but I can't find how to implement the badge configuration:

let badgeAnchor = NSCollectionLayoutAnchor(edges: [.top, .trailing], fractionalOffset: CGPoint(x: 0.3, y: -0.3))
let badgeSize = NSCollectionLayoutSize(widthDimension: .absolute(20),
                                                  heightDimension: .absolute(20))
let badge = NSCollectionLayoutSupplementaryItem(
                layoutSize: badgeSize,
                elementKind: "badge",
                containerAnchor: badgeAnchor)

like the example code Apple provides:

let item = NSCollectionLayoutItem(layoutSize: itemSize, supplementaryItems: [badge])

(the example code that Apple provides, crashes btw)

Any ideas on how to implement the badge to UICollectionLayoutListConfiguration or is not possible?

3 Answers

In the sample project, element kind for badge was wrong. It was

let badge = NSCollectionLayoutSupplementaryItem(
            layoutSize: badgeSize,
            elementKind: ItemBadgeSupplementaryViewController.badgeElementKind,
            containerAnchor: badgeAnchor)

and the error message actually made sense:

"the view returned from -collectionView:viewForSupplementaryElementOfKind:atIndexPath: does not match the element kind it is being used for. When asked for a view of element kind 'badge-element-kind' the data source dequeued a view registered for the element kind 'badge-reuse-identifier'."

Just change elementKind of the badge (in ItemBadgeSupplementaryViewController) to

elementKind: BadgeSupplementaryView.reuseIdentifier

And to answer your question, the badge will be a supplementary item of your NSCollectionLayoutItem.

Instead of using supplementary views, I found adding a basic badge accessory view is somewhat simpler.

let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, ContentItem> {[weak self] (cell, indexPath, contentItem) in

    // Set item data in cell
    var config = cell.defaultContentConfiguration()
    config.image = contentItem.image
    config.text = contentItem.name
    cell.contentConfiguration = config

    // Add an unread count badge if there are unread items.
    if contentItem.unreadCount != 0 {
        let badgeLabel = UILabel()
        badgeLabel.backgroundColor = .red
        badgeLabel.textColor = .white
        badgeLabel.layer.cornerRadius = 10
        badgeLabel.clipsToBounds = true
        badgeLabel.text = "  \(contentItem.unreadCount)  "
        let viewConfig = UICellAccessory.CustomViewConfiguration(customView: badgeLabel, placement: .trailing(displayed: .always))
        let badgeAccessory = UICellAccessory.customView(configuration: viewConfig)
        cell.accessories = [badgeAccessory]
    }
}
Related