74 lines
2.7 KiB
Swift
74 lines
2.7 KiB
Swift
//
|
|
// SelfSizingCollectionView.swift
|
|
// VDS
|
|
//
|
|
// Created by Matt Bruce on 11/18/22.
|
|
//
|
|
|
|
import Foundation
|
|
import UIKit
|
|
|
|
@objc(VDSSelfSizingCollectionView)
|
|
public final class SelfSizingCollectionView: UICollectionView {
|
|
|
|
private var contentSizeObservation: NSKeyValueObservation?
|
|
|
|
// MARK: - Lifecycle
|
|
|
|
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: - UIView
|
|
|
|
public override var intrinsicContentSize: CGSize {
|
|
let contentSize = self.contentSize
|
|
//print(#function, contentSize)
|
|
return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
|
|
}
|
|
|
|
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()
|
|
}
|
|
}
|
|
|
|
public override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
|
|
let size = super.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: horizontalFittingPriority, verticalFittingPriority: verticalFittingPriority)
|
|
//print(type(of: self), #function, targetSize, "->", size)
|
|
return size
|
|
}
|
|
|
|
// MARK: - Private
|
|
|
|
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 {
|
|
|
|
public func hasDifferentTextAppearance(comparedTo traitCollection: UITraitCollection?) -> Bool {
|
|
var result = self.preferredContentSizeCategory != traitCollection?.preferredContentSizeCategory
|
|
result = result || self.legibilityWeight != traitCollection?.legibilityWeight
|
|
return result
|
|
}
|
|
}
|
|
|