0

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 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Looks great! The only concern I have is that itemSeparatorHandler is only available for iOS 14.5+. I guess the solution for older iOS versions would be what @OneCommentMan suggested: just add a line to the bottom of cells?
Your own line should work but getting the correct appearance and leading margin can be tricky. The separators are probably using UIColor.separator (which is partially transparent). They are also 1 pixel, not 1 point, tall. You would need to set a fractional height constraint based on the 2x/3x resolution of the screen (i.e. 0.5 for 2x and 0.333 for 3x). UICollectionViewListCell has a separatorLayoutGuide but it looks like that might only be valid when the system's separators are enabled.
separatorLayoutGuide worked. It's actually valid even when separators are disabled. So all that's required to do here is constraint my fake separator to separatorLayoutGuide and that's it.
1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.