Background:
iOS14 has introduced a new way to register and configure collectionViewCell and In Lists In CollectionView WWDC video apple developer says that self sizing is default to UICollectionViewListCell and we don't have to explicitly specify the height for cells. This works great if I use system list cell in various configurations but self sizing fails when I use it with custom subclass of UICollectionViewListCell
What have I tried?
iOS 14 has introduced a new way to configure the cells, where we don't access the cells components directly to set the various UI properties rater we use content configuration and background configuration to update/configure cells. This becomes little tricky when we use custom cells.
CustomSkillListCollectionViewCell
class CustomSkillListCollectionViewCell: UICollectionViewListCell {
var skillLavel: String? {
didSet {
setNeedsUpdateConfiguration()
}
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func updateConfiguration(using state: UICellConfigurationState) {
backgroundConfiguration = SkillListViewBackgroundConfiguration.getBackgroundConfiguration(for: state)
var content = SkillListViewContentConfiguration().updated(for: state)
content.label = skillLavel
contentConfiguration = content
}
}
SkillListViewBackgroundConfiguration
struct SkillListViewBackgroundConfiguration {
@available(iOS 14.0, *)
static func getBackgroundConfiguration(for state: UICellConfigurationState) -> UIBackgroundConfiguration {
var background = UIBackgroundConfiguration.clear()
if state.isHighlighted || state.isSelected {
background.backgroundColor = UIColor.green.withAlphaComponent(0.4)
}
else if state.isExpanded {
background.backgroundColor = UIColor.red.withAlphaComponent(0.5)
}
else {
background.backgroundColor = UIColor.red.withAlphaComponent(0.9)
}
return background
}
}
SkillListViewContentConfiguration
struct SkillListViewContentConfiguration: UIContentConfiguration {
var label: String? = nil
@available(iOS 14.0, *)
func makeContentView() -> UIView & UIContentView {
return SkillListView(contentConfiguration: self)
}
@available(iOS 14.0, *)
func updated(for state: UIConfigurationState) -> Self {
guard let state = state as? UICellConfigurationState else {
return self
}
let updatedConfig = self
return updatedConfig
}
}
Finally subview SkillListView
class SkillListView: UIView, UIContentView {
var configuration: UIContentConfiguration {
get {
return self.appliedConfiguration
}
set {
guard let newConfig = newValue as? SkillListViewContentConfiguration else { return }
self.appliedConfiguration = newConfig
apply()
}
}
private var appliedConfiguration: SkillListViewContentConfiguration!
var skillNameLabel: UILabel!
@available(iOS 14.0, *)
init(contentConfiguration: UIContentConfiguration) {
super.init(frame: .zero)
self.setUpUI()
self.configuration = contentConfiguration
self.apply()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func apply() {
self.skillNameLabel.text = self.appliedConfiguration.label
}
private func setUpUI() {
self.skillNameLabel = UILabel(frame: .zero)
skillNameLabel.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
skillNameLabel.setContentHuggingPriority(.defaultHigh, for: .vertical)
self.skillNameLabel.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(skillNameLabel)
NSLayoutConstraint.activate([
self.skillNameLabel.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor, constant: 20),
self.skillNameLabel.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor, constant: 20),
self.skillNameLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor, constant: 20)
])
}
}
And I configure it using
let skillsCellConfigurator = UICollectionView.CellRegistration<CustomSkillListCollectionViewCell, Employee> { (cell, indexPath, employee) in
cell.skillLavel = employee.individualSkil
cell.accessories = [.disclosureIndicator()]
}
Issue:
Everything else works great except height
