vds_ios/VDS/Classes/SelfSizingCollectionView.swift
Matt Bruce bb158f506f updated docs and comments
Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
2023-08-29 08:51:13 -05:00

85 lines
3.4 KiB
Swift

//
// SelfSizingCollectionView.swift
// VDS
//
// Created by Matt Bruce on 11/18/22.
//
import Foundation
import UIKit
/// UICollectionView subclassed to deal with Changing the size of itself based on its children and layout and changes of its contentSize.
@objc(VDSSelfSizingCollectionView)
public final class SelfSizingCollectionView: UICollectionView {
//--------------------------------------------------
// MARK: - Initialization
//--------------------------------------------------
/// Initializer
/// - Parameters:
/// - frame: Frame needed
/// - layout: Layout used for this CollectionView
public override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
super.init(frame: frame, collectionViewLayout: layout)
self.setupContentSizeObservation()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
self.setupContentSizeObservation()
}
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
private var contentSizeObservation: NSKeyValueObservation?
//--------------------------------------------------
// MARK: - Overrides
//--------------------------------------------------
/// The natural size for the receiving view, considering only properties of the view itself.
public override var intrinsicContentSize: CGSize {
let contentSize = self.contentSize
//print(#function, contentSize)
return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
}
/// Overridden to deal with Appearance Changes
public override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
//print(type(of: self), #function)
super.traitCollectionDidChange(previousTraitCollection)
// We need to handle any change that will affect layout and/or anything that affects size of a UILabel
if self.traitCollection.hasDifferentTextAppearance(comparedTo: previousTraitCollection) {
self.collectionViewLayout.invalidateLayout()
}
}
//--------------------------------------------------
// MARK: - Private Methods
//--------------------------------------------------
private func setupContentSizeObservation() {
// Observing the value of contentSize seems to be the only reliable way to get the contentSize after the collection view lays out its subviews.
self.contentSizeObservation = self.observe(\.contentSize, options: [.old, .new]) { [weak self] _, change in
// If we don't specify `options: [.old, .new]`, the change.oldValue and .newValue will always be `nil`.
if change.newValue != change.oldValue {
self?.invalidateIntrinsicContentSize()
}
}
}
}
extension UITraitCollection {
/// Used within SelfSizingCollectionView to determine if there is an appearance change.
/// - Parameter traitCollection: TraitCollection to compare.
/// - Returns: True/False based on the trailCollection passed in.
public func hasDifferentTextAppearance(comparedTo traitCollection: UITraitCollection?) -> Bool {
var result = self.preferredContentSizeCategory != traitCollection?.preferredContentSizeCategory
result = result || self.legibilityWeight != traitCollection?.legibilityWeight
return result
}
}