はじめに
この記事では、カレンダーの月によって行数が変化した際に、カレンダー全体の高さを動的に変更するポイントを紹介します。
結論
gifでは2021年5月は6行になるため、カレンダー全体の高さがそれに合わせて変化しています。
検証環境
端末 | バージョン |
---|---|
Mac | Big Sur 11.2.3 |
Xcode | 12.5 |
Swift | 5 |
iOS | 13.0 |
UIKit |
前提条件
UIViewControllerのtop,right,bottom,leftにUICollectionViewを合わせてレイアウトを設定しています。
コード
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let height = collectionView.collectionViewLayout.collectionViewContentSize.height
if height != view.frame.size.height {
heightConstraint = collectionView.heightAnchor.constraint(equalToConstant: height)
heightConstraint?.isActive = true
self.view.setNeedsLayout()
self.view.layoutIfNeeded()
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
collectionView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
if let height = heightConstraint {
height.isActive = false
heightConstraint = collectionView.heightAnchor.constraint(equalToConstant: collectionView.collectionViewLayout.collectionViewContentSize.height)
heightConstraint!.isActive = true
}
}
解説
viewDidAppearでレイアウトが確定したタイミングでUICollectionViewLayoutのcollectionViewContentSize.heightがカレンダー全体の高さと一致していなければNSLayoutConstraintに保持しています。
その後、viewDidLayoutSubviewsでNSLayoutConstraintに保持している高さを一度無効とし、再度高さを設定しています。
これはカレンダーの月を変更した場合に、前回登録している高さを一度無効化しておかなければ制約の重複が発生するためです。
当初はカレンダーの高さを取得するのにUICollectionView.contentSize.heightを使用していましたが、これだと次の月が表示された時点で、新しいカレンダーの高さが取得できなかったため、UICollectionViewLayoutのcollectionViewContentSize.heightを使用しています。(1つ前の月の高さのままでした)
参照
collectionViewContentSize | Apple Developer Documentation
The width and height of the collection view’s contents.
コメント