// // ProfileHeaderCollectionViewCell.swift // Tusker // // Created by Shadowfacts on 10/10/22. // Copyright © 2022 Shadowfacts. All rights reserved. // import UIKit class ProfileHeaderCollectionViewCell: UICollectionViewCell { private var state: State = .unloaded var view: ProfileHeaderView? { if case .view(let view) = state { return view } else { return nil } } override init(frame: CGRect) { super.init(frame: frame) contentView.backgroundColor = .appBackground isOpaque = true contentView.isOpaque = true } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func addHeader(_ header: ProfileHeaderView) { switch state { case .unloaded, .placeholder(heightConstraint: _): header.translatesAutoresizingMaskIntoConstraints = false contentView.embedSubview(header) self.state = .view(header) case .view(_): fatalError("profile header collection view cell already has view") } } func addConstraint(height: CGFloat) -> ProfileHeaderView? { switch state { case .unloaded: let constraint = contentView.heightAnchor.constraint(equalToConstant: height) constraint.isActive = true state = .placeholder(heightConstraint: constraint) return nil case .placeholder(let heightConstraint): heightConstraint.constant = height return nil case .view(let header): let constraint = contentView.heightAnchor.constraint(equalToConstant: height) constraint.isActive = true state = .placeholder(heightConstraint: constraint) return header } } // overrides an internal method // when the super impl is used, preferredLayoutAttributesFitting(_:) isn't called while the view is offscreen (i.e., window == nil) // and so the collection view imposes a height of 44pts which breaks the layout @objc func _preferredLayoutAttributesFittingAttributes(_ attributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes { return preferredLayoutAttributesFitting(attributes) } enum State { case unloaded case placeholder(heightConstraint: NSLayoutConstraint) case view(ProfileHeaderView) } }