Last active
August 31, 2021 00:36
-
-
Save romyios/d5ce0cc2451d43827fbc37f194289a5a to your computer and use it in GitHub Desktop.
From apple's modernizing collection view
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private class CustomListCell: ItemListCell { | |
private func defaultListContentConfiguration() -> UIListContentConfiguration { return .subtitleCell() } | |
private lazy var listContentView = UIListContentView(configuration: defaultListContentConfiguration()) | |
private let categoryIconView = UIImageView() | |
private let categoryLabel = UILabel() | |
private var customViewConstraints: (categoryLabelLeading: NSLayoutConstraint, | |
categoryLabelTrailing: NSLayoutConstraint, | |
categoryIconTrailing: NSLayoutConstraint)? | |
private func setupViewsIfNeeded() { | |
// We only need to do anything if we haven't already setup the views and created constraints. | |
guard customViewConstraints == nil else { return } | |
contentView.addSubview(listContentView) | |
contentView.addSubview(categoryLabel) | |
contentView.addSubview(categoryIconView) | |
listContentView.translatesAutoresizingMaskIntoConstraints = false | |
let defaultHorizontalCompressionResistance = listContentView.contentCompressionResistancePriority(for: .horizontal) | |
listContentView.setContentCompressionResistancePriority(defaultHorizontalCompressionResistance - 1, for: .horizontal) | |
categoryLabel.translatesAutoresizingMaskIntoConstraints = false | |
categoryIconView.translatesAutoresizingMaskIntoConstraints = false | |
let constraints = ( | |
categoryLabelLeading: categoryLabel.leadingAnchor.constraint(greaterThanOrEqualTo: listContentView.trailingAnchor), | |
categoryLabelTrailing: categoryIconView.leadingAnchor.constraint(equalTo: categoryLabel.trailingAnchor), | |
categoryIconTrailing: contentView.trailingAnchor.constraint(equalTo: categoryIconView.trailingAnchor) | |
) | |
NSLayoutConstraint.activate([ | |
listContentView.topAnchor.constraint(equalTo: contentView.topAnchor), | |
listContentView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), | |
listContentView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), | |
categoryLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), | |
categoryIconView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), | |
constraints.categoryLabelLeading, | |
constraints.categoryLabelTrailing, | |
constraints.categoryIconTrailing | |
]) | |
customViewConstraints = constraints | |
} | |
private var separatorConstraint: NSLayoutConstraint? | |
private func updateSeparatorConstraint() { | |
guard let textLayoutGuide = listContentView.textLayoutGuide else { return } | |
if let existingConstraint = separatorConstraint, existingConstraint.isActive { | |
return | |
} | |
let constraint = separatorLayoutGuide.leadingAnchor.constraint(equalTo: textLayoutGuide.leadingAnchor) | |
constraint.isActive = true | |
separatorConstraint = constraint | |
} | |
/// - Tag: UpdateConfiguration | |
override func updateConfiguration(using state: UICellConfigurationState) { | |
setupViewsIfNeeded() | |
// Configure the list content configuration and apply that to the list content view. | |
var content = defaultListContentConfiguration().updated(for: state) | |
content.imageProperties.preferredSymbolConfiguration = .init(font: content.textProperties.font, scale: .large) | |
content.image = state.item?.image | |
content.text = state.item?.title | |
content.secondaryText = state.item?.description | |
content.axesPreservingSuperviewLayoutMargins = [] | |
listContentView.configuration = content | |
// Get the list value cell configuration for the current state, which we'll use to obtain the system default | |
// styling and metrics to copy to our custom views. | |
let valueConfiguration = UIListContentConfiguration.valueCell().updated(for: state) | |
// Configure custom image view for the category icon, copying some of the styling from the value cell configuration. | |
categoryIconView.image = state.item?.category.icon | |
categoryIconView.tintColor = valueConfiguration.imageProperties.resolvedTintColor(for: tintColor) | |
categoryIconView.preferredSymbolConfiguration = .init(font: valueConfiguration.secondaryTextProperties.font, scale: .small) | |
// Configure custom label for the category name, copying some of the styling from the value cell configuration. | |
categoryLabel.text = state.item?.category.name | |
categoryLabel.textColor = valueConfiguration.secondaryTextProperties.resolvedColor() | |
categoryLabel.font = valueConfiguration.secondaryTextProperties.font | |
categoryLabel.adjustsFontForContentSizeCategory = valueConfiguration.secondaryTextProperties.adjustsFontForContentSizeCategory | |
// Update some of the constraints for our custom views using the system default metrics from the configurations. | |
customViewConstraints?.categoryLabelLeading.constant = content.directionalLayoutMargins.trailing | |
customViewConstraints?.categoryLabelTrailing.constant = valueConfiguration.textToSecondaryTextHorizontalPadding | |
customViewConstraints?.categoryIconTrailing.constant = content.directionalLayoutMargins.trailing | |
updateSeparatorConstraint() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This list cell subclass is an abstract class with a property that holds the item the cell is displaying, | |
// which is added to the cell's configuration state for subclasses to use when updating their configuration. | |
private class ItemListCell: UICollectionViewListCell { | |
private var item: Item? = nil | |
func updateWithItem(_ newItem: Item) { | |
guard item != newItem else { return } | |
item = newItem | |
setNeedsUpdateConfiguration() | |
} | |
override var configurationState: UICellConfigurationState { | |
var state = super.configurationState | |
state.item = self.item | |
return state | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// thank you apple! | |
@available(iOS 6.0, *) | |
open class UICollectionViewCell : UICollectionReusableView { | |
/// Requests the cell update its configuration for its current state. This method is called automatically | |
/// when the cell's `configurationState` may have changed, as well as in other circumstances where an | |
/// update may be required. Multiple requests may be coalesced into a single update at the appropriate time. | |
@available(iOS 14.0, *) | |
open func setNeedsUpdateConfiguration() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment