UICollectionView: remove separators for specific cells only

740 Views Asked by At

I need to show separators for every cell in UICollectionView except every first cell of a section. I'm using list layout. So far I have only been able to remove all separators using configuration.showsSeparators = false.

My UICollectionView configuration:

let collectionView: UICollectionView = {
    let provider = { (_: Int, layoutEnv: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
        var configuration = UICollectionLayoutListConfiguration(appearance: .grouped)
        configuration.showsSeparators = true // <----- shows separators for every cell
        configuration.footerMode = .supplementary
        return .list(using: configuration, layoutEnvironment: layoutEnv)
    }
    let listLayout = UICollectionViewCompositionalLayout(sectionProvider: provider)
    return UICollectionView(frame: .zero, collectionViewLayout: listLayout)
}()

Cell registartion:

let cellRegistration = UICollectionView.CellRegistration<MailboxCell, MailAccount> {
    (cell, indexPath, listItem) in
    // some setup code
}

dataSource = UICollectionViewDiffableDataSource<Account, ListItem>(collectionView: collectionView) { 
    (collectionView, indexPath, listItem) -> UICollectionViewCell? in

    // some setup
    return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: listItem)
}

2

There are 2 best solutions below

3
Geoff Hackworth On BEST ANSWER

UICollectionLayoutListConfiguration has a handler closure which allows you to configure the separator appearance on an item-by-item basis: itemSeparatorHandler (https://developer.apple.com/documentation/uikit/uicollectionlayoutlistconfiguration/3727737-itemseparatorhandler).

If you don't want bottom separators for the first item in each section you can add a handler to your UICollectionLayoutListConfiguration that hides the separator for the first item:

let collectionView: UICollectionView = {
    let provider = { (_: Int, layoutEnv: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
        var configuration = UICollectionLayoutListConfiguration(appearance: .grouped)
        configuration.footerMode = .supplementary

        // Hide bottom separator for first item in each section
        configuration.itemSeparatorHandler = { indexPath, sectionSeparatorConfiguration in
            var configuration = sectionSeparatorConfiguration
            configuration.bottomSeparatorVisibility = indexPath.row == 0 ? .hidden : .visible
            return configuration
        }

        return .list(using: configuration, layoutEnvironment: layoutEnv)
    }
    let listLayout = UICollectionViewCompositionalLayout(sectionProvider: provider)
    return UICollectionView(frame: .zero, collectionViewLayout: listLayout)
}()

It looks like showsSeparators defaults to true for the grouped appearance so you don't need to explicitly set that.

If you also want to remove the top separator you can easily do that too by adjusting topSeparatorVisibility in the handler in the same way.

0
OneCommentMan On

One possible solution is remove the default separators by setting configuration.showsSeparators = false. Then add a line view at the bottom of the cell's UI to create the illusion of a separator.