I have a really simple UICollectionView, using iOS 13's UICollectionViewCompositionalLayout. The cells have a vertical UIStackView, and when you press the "toggle details" button, I simple change the isHidden value of the detailsView. When the cells then inform the view controller that it needs to execute collectionView.collectionViewLayout.invalidateLayout(), everything basically works: the details view is toggled on and off. But it doesn't animate this, so it looks a bit jarring.
class ViewController: UIViewController {
@IBOutlet private var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
collectionView.collectionViewLayout = createLayout()
}
private func createLayout() -> UICollectionViewLayout {
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(200))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(200))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.contentInsets = .init(top: 16, leading: 16, bottom: 16, trailing: 16)
section.interGroupSpacing = 16
let layout = UICollectionViewCompositionalLayout(section: section)
return layout
}
}
extension ViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
cell.resize = { [weak self] in
UIView.animate(withDuration: 2) {
self?.collectionView.collectionViewLayout.invalidateLayout()
}
}
return cell
}
}
class Cell: UICollectionViewCell {
@IBOutlet private var detailsView: UIView!
var resize: (() -> Void)?
override func awakeFromNib() {
super.awakeFromNib()
contentView.layer.cornerRadius = 10
}
@IBAction private func toggleDetails() {
detailsView.isHidden.toggle()
resize?()
}
}
Repro project: https://github.com/kevinrenskers/CellHeight.
How can I animate the toggling of this details view, so that the height change animates? And can that be used in combination with the UIStackView and showing/hiding its children views? Please note that the details view doesn't have a fixed height in the real world app, so I can't just switch the cell height between two fixed values.

