swiftui

【LazyGrid】SwiftUIでCollectionViewを作る方法

分かりやすいようにミニマム構成で解説しています。LazyGridの登場でSwiftUIへの移行も現実味を帯びてきた感がありますね。

SwiftUIでCollectionViewの実装を行うには

まず初めに概要を簡単に説明します

  • LazyGridを使うことで、グリッド状のViewを作る事ができます
  • LazyVGrid(縦方向グリッド)とLazyHGrid(横方向グリッド)の2種類が存在します
  • GridItemでセルのレイアウトを定義することができます
補足

以前はSwiftUIでCollectionViewのようなViewを作る方法として有志の方が作ったライブラリを使うという方法がありましたが、iOS14から公式の方法としてLazyGridが提供されました。グリッド状ののViewはリスト状のviewに次いで活用頻度が多いため、待望だったという方も多いと思います。基本的にはこのLazyGridを使っていくことになると思います。

解説

画像のように横9 * 縦3 合計27ののグリッドを作ります。余談ですが、個人開発アプリの野球のスコアボードとして使う予定。

sample

GridItemの定義

GridItemはUIKitでいうところのCellに相当します。このように配列として定義しておきます。サンプルコードではrepeatingを使って全て同じGridItemで構成しています。一行あたり必要なGridは9個なのでcount:には9を渡します。

struct ScoreView: View {
  private var columns: [GridItem] = Array(repeating: .init(.flexible(minimum: 10), spacing: CGFloat(0.0) ), count: 9)
  
  var body: some View {
    
  }

}

ちなみに同じ大きさだけではなく、異なる大きさのGridItemを混ぜたりもできます。詳しいやり方はページでは割愛しますが、こちらが参考になります。

引数

GridItemを定義する際に必要な引数は次の2つです。

  • size
.fixed.flexible.adaptive
サイズを直接指定可変(最小及び最大値を指定可)可変(最小及び最大値を指定可)
特になしViewに入る最大のサイズでViewに詰め込めるだけ詰め込む
.fixed(10).flexible(minimum: 10).adaptive(minimum: 10,maximum 100)
  • spacing

LazyVGridの場合はLazyGridのspacingに渡す値で縦の間隔を、GridItemのspacingで横の間隔を調整できます。LazyHGridは逆になります。こちらが参考になります。

LazyGridの定義

LazyVGrid(columns: [GridItem], alignment: HorizontalAlignment, spacing: CGFloat?) { }
LazyHGrid(rows: [GridItem], alignment: .center, spacing: 0) { }
引数

定義の際に必要な引数は次の3つです。

  • columns
    LazyHGridの場合はrowsとなります。先ほど定義した配列のGridItemを渡します。
  • alignment
    左詰め(.leading)・右詰め(.trailling)・中央(.center)の三択
  • spacing
    なくても良いですが、使うことになると思います。LazyVGridの場合は横の間隔、LazyHGridは縦の間隔です。
描画

今回は「9 * 3」のグリッドを作りたいので合計27個のGridItemが必要となります。ForEachを活用して生成します。

    var body: some View {
        ScrollView(.vertical) {
            LazyVGrid(columns: columns, alignment: .center, spacing: 0) {
                ForEach((1...27), id: \.self) { num in
                    Text("\(num)")
                }
            }
        }
    }

数字が羅列されているだけで殺風景なので背景色をつけます。縦横比1:1の正方形に色をつけてTextの裏に配置しています。ZStackを活用することでZ軸(奥行き)方向にViewを重ねることができます。

    var body: some View {
        ScrollView(.vertical) {
            LazyVGrid(columns: columns, alignment: .center, spacing: 0) {
                ForEach((1...27), id: \.self) { num in
                    ZStack {
                        Rectangle().foregroundColor(.green)
                            .aspectRatio(1,contentMode: .fill)
                            .border(Color.black)
                        Text("\(num)")
                    }
                }
            }
        }
    }

これで完成です。

参考

読んでいただきありがとうございます!!

記事として取り上げたトピックを体系化してまとめた内容を電子書籍として販売しています。購入していただくことで執筆の応援ができます。詳細はこちらから