CollectionViewで画面回転に対応するときもCompositionalLayoutを使うのが良さそう
CompotionalLayout
、便利ですよね。
CollectionView
での複雑なレイアウト構築にも役立ちますが、画面回転時にも便利なことに気付いたのでまとめてみました。
CompotionalLayout の画面回転時の便利なところ
- 画面回転時などCollectionViewのサイズが変わると UICollectionViewCompositionalLayout の再生成が行われる
従来の UICollectionViewLayout
では 画面回転時にレイアウトを更新したい場合、 invalidateLayout()
を呼び出す必要がありました。
一方で UICollectionViewCompositionalLayout
では、画面回転時などCollectionViewのサイズが変わると自動的に再生成が行われます。
したがって、こちらで意識しなくても画面回転時のレイアウト更新が可能となります。
- NSCollectionLayoutEnvironment で traitCollection などを取得可能
UICollectionViewCompositionalLayoutSectionProvider
を使った initialize で NSCollectionLayoutEnvironment
の取得が可能です。
NSCollectionLayoutEnvironment
には UITraitCollection
と NSCollectionLayoutContainer
が含まれており、これを元に次のレイアウトをどう組むかを判断できます。
コード例
上記の便利なところを活かすと、こんなコードで画面回転時の対応が出来ます。
let layout = UICollectionViewCompositionalLayout {(section: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
let widthFraction: CGFloat
let traitCollection = layoutEnvironment.traitCollection
switch (traitCollection.horizontalSizeClass, traitCollection.verticalSizeClass) {
case (.compact, .compact):
// iPhone 縦持ちの時はCollectionViewの半分をItemの幅に
widthFraction = 1 / 2
default:
widthFraction = 1 / 4
}
let itemSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(widthFraction),
heightDimension: .absolute(100))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1),
heightDimension: .fractionalWidth(1))
let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitems: [item])
return NSCollectionLayoutSection(group: group)
}
このコード例では、 layoutEnvironment.traitCollection
を参照することで、iPhoneでの横持ちの時のレイアウトに対応しています。
このように UICollectionViewCompositionalLayout
を生成するロジックを組んでおくことで、画面回転時などCollectionViewのサイズが変更された時に、再生成が行われます。
もし画面回転に対応したアプリでCollectionViewを使っている場合、 UICollectionViewCompositionalLayout
の利用をおすすめします。
Discussion