🦔

CollectionViewで画面回転に対応するときもCompositionalLayoutを使うのが良さそう

2023/02/27に公開

CompotionalLayout 、便利ですよね。
CollectionView での複雑なレイアウト構築にも役立ちますが、画面回転時にも便利なことに気付いたのでまとめてみました。

CompotionalLayout の画面回転時の便利なところ

  1. 画面回転時などCollectionViewのサイズが変わると UICollectionViewCompositionalLayout の再生成が行われる

従来の UICollectionViewLayout では 画面回転時にレイアウトを更新したい場合、 invalidateLayout() を呼び出す必要がありました。
https://developer.apple.com/documentation/uikit/uicollectionviewlayout/1617728-invalidatelayout

一方で UICollectionViewCompositionalLayout では、画面回転時などCollectionViewのサイズが変わると自動的に再生成が行われます。
したがって、こちらで意識しなくても画面回転時のレイアウト更新が可能となります。

  1. NSCollectionLayoutEnvironment で traitCollection などを取得可能

UICollectionViewCompositionalLayoutSectionProvider を使った initialize で NSCollectionLayoutEnvironment の取得が可能です。
NSCollectionLayoutEnvironment には UITraitCollectionNSCollectionLayoutContainer が含まれており、これを元に次のレイアウトをどう組むかを判断できます。

コード例

上記の便利なところを活かすと、こんなコードで画面回転時の対応が出来ます。

 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