The following is a UIKit app that displays a collection view with list layout and diffable data source (one section, one row).
class ViewController: UIViewController {
var collectionView: UICollectionView!
var dataSource: UICollectionViewDiffableDataSource<String, String>!
override func viewDidLoad() {
super.viewDidLoad()
configureHierarchy()
configureDataSource()
}
func configureHierarchy() {
collectionView = .init(frame: .zero, collectionViewLayout: createLayout())
view.addSubview(collectionView)
collectionView.frame = view.bounds
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
func createLayout() -> UICollectionViewLayout {
UICollectionViewCompositionalLayout { section, layoutEnvironment in
let config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
return NSCollectionLayoutSection.list(using: config, layoutEnvironment: layoutEnvironment)
}
}
func configureDataSource() {
let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, String> { cell, indexPath, itemIdentifier in
var backgroundConfiguration = UIBackgroundConfiguration.listGroupedCell()
backgroundConfiguration.backgroundColor = .systemBlue
cell.backgroundConfiguration = backgroundConfiguration
}
dataSource = .init(collectionView: collectionView) { collectionView, indexPath, itemIdentifier in
collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: itemIdentifier)
}
var snapshot = NSDiffableDataSourceSnapshot<String, String>()
snapshot.appendSections(["main"])
snapshot.appendItems(["demo"])
dataSource.apply(snapshot, animatingDifferences: false)
}
}
If you tap on the row, it seems like selection doesn't happen: giving the cell a blue background broke its default background color transformer.
Here's what I've tried and didn't work:
- Setting the collection view's delegate and specifying that you can select any row
- Setting the color transformer to
.grayscale
- Setting the backgroundConfiguration to
UIBackgroundConfiguration.listGroupedCell().updated(for: cell.configurationState)
- Combinations of the approaches above
- Setting the color transformer to
UIBackgroundConfiguration.listGroupedCell().backgroundColorTransformer
andcell.backgroundConfiguration?.backgroundColorTransformer
(they're both nil) - Setting the cell's
backgroundColor
directly
I also considered using a custom color transformer:
var backgroundConfiguration = UIBackgroundConfiguration.listGroupedCell()
backgroundConfiguration.backgroundColorTransformer = UIConfigurationColorTransformer { _ in
if cell.configurationState.isSelected || cell.configurationState.isHighlighted {
.systemBlue.withAlphaComponent(0.7)
} else {
.systemBlue
}
}
cell.backgroundConfiguration = backgroundConfiguration
However, if you push a view controller when you select the row, the row gets deselected, which is unfortunate, giving that I like to deselect rows in viewWillAppear(_:)
to keep users more oriented.
There might be ways to circumvent this, but my custom color transformer might still differ from the default one in some other ways.
So how do I assign the default one to my cell?