見出し画像

[SwiftUI]「LazyGrid」を使ったViewデザインに触れてみる

◎あいさつ


おはようございます。

中川(Twitter)です。みなさんいかがお過ごしでしょうか?
私の家には専用の粉を入れて作る自動コーヒーマシン?(安いやつ)なるものが置いてあるのですが、
先日豆を切らしたので、いつもと違う味を買って見たところ、ハチャメチャに苦かったです。あと何十杯分かはこの味です。。辛い☕️

さて、今回はSwiftUIの機能「LagyGlid」を触ってみたいと思います。
UIKitでいうところのUICollectionViewと似た挙動を持っているようですね。
早速トライしていきましょう。

■はじめに


・LagyGridって?

LazyGridはUIKitでいうCollectionViewのようなグリッド状のViewを作成することができるiOS14から提供されたSwiftUIの実装手法です。

・解説

https://www.hackingwithswift.com/quick-start/swiftui/how-to-position-views-in-a-grid-using-lazyvgrid-and-lazyhgrid

SwiftUI's LazyVGrid and LazyHGrid give us grid layouts with a fair amount of flexibility. The simplest possible grid is made up of three things: your raw data, an array of GridItem describing the layout you want, and either a LazyVGrid or a LazyHGrid that brings together your data and your layout.

[訳]
SwiftUI の LazyVGrid と LazyHGrid はかなりの量の柔軟性を持つグリッドレイアウトを提供します。グリッドは3つのものから簡単に構成されます。
・元となるアイテムデータ
・必要なレイアウトを記述するGridItemの配列
・データとレイアウトをまとめるLazyVGridまたはLazyHGridのどちらか

の3つです。

HACKING WITH SWIFTより

■実装の流れ


先に大まかな実装手順を見ておきます。

・手順

1.  GridItemの作成(ここでセルのレイアウトを定義)
2. Lazy(V or H)Grid(columun: <GridItem名>) {} を作成
3. ⬆︎のクロージャ内にアイテムを定義
4. ループ文でクロージャ内に定義したアイテムを必要数生成

上記にあるように、RazyGridには大きく分けて二つ、
RazyVGridRazyHGridgがあります。
それぞれの実装例を見ていきましょう。

■Razy"V"Gridの実装例

RaZyVGridは、GridItemで指定したセルのレイアウトを参考にしながら、
縦方向に向かって積まれていきます。

struct LazyVGridView: View {

    // GridItemを作成
    private var vGridItem: [GridItem] = [GridItem(.adaptive(minimum: 70), spacing: 5)]

    var body: some View {

        NavigationView {
            ScrollView {

                // アイテムをLazyGridで囲む 引数にGridItemを指定
                LazyVGrid(columns: vGridItem, alignment: .center, spacing: 10) {

                    // 指定の数分アイテムを定義
                    ForEach(1...9, id: \.self) { id in

                        VStack {

                            // LazyGridクロージャ内でアイテムのデザインを定義
                            Image(systemName: "folder")
                                .resizable()
                                .scaledToFit()
                                .frame(width: 50, height: 50)

                            Text("\(id)")
                                .font(.body)

                        }
                        .padding()
                        .background(.yellow)

                    } // ForEach
                } // LazaVGrid
            } // ScrollView
            .navigationTitle("LazyVGridView")
        }// NavigationView


    } // body
} // View
RazyVGridの実装例

プロパティとして生成されたGridItemのレイアウト指定に従って
ForEachで回した数分アイテムを並べてくれていますね✊

これらを用いて、ForEachで指定するアイテムにも一工夫入れると…

ゲームのメニューにあるような感じにも並べることができます。

struct Item: Identifiable {
    var id = UUID()
    var name: String
    var image: String
}

struct LazyVGridView2: View {

    let items = [Item(name: "item", image: "latch.2.case.fill"),
                 Item(name: "character", image: "person.fill"),
                 Item(name: "map", image: "globe.asia.australia.fill"),
                 Item(name: "mail", image: "envelope.fill"),
                 Item(name: "save", image: "magazine.fill"),
                 Item(name: "cystem", image: "gamecontroller.fill")]

    let gridItem: [GridItem] = [GridItem(.adaptive(minimum: 100, maximum: 150))]

    var body: some View {

        NavigationView {
            ScrollView {
                LazyVGrid(columns: gridItem, alignment: .center, spacing: 5) {

                    ForEach(items) { item in

                        VStack {
                            Image(systemName: item.image)
                                .resizable()
                                .scaledToFit()
                                .frame(width: 25, height: 25)
                                .foregroundColor(.white)

                            Text(item.name)
                                .font(.body)
                                .foregroundColor(.white)
                        }
                        .frame(width: 120, height: 100)
                        .border(Color.black, width: 1)
                        .background(.gray)
                        .cornerRadius(20)

                    }
                }
                .padding()
            }
            .navigationTitle("メニュー")
        }
    }
}

また、GridItemの引数minimum: 100の値を変えてやると、

minimum:100 ⇨ 120

このように押し出されて縦二列になったりします。
これは1アイテムごとのセル範囲が変わったためです。
View内の横範囲に入る分だけ置いていき、入り切らないアイテムは下へ下へ繰り越されていくという縦の挙動の特徴ですね。
Razy「V」Gridと「V」Stackでまとめて考えるとイメージしやすいです。

■Razy"H"Gridの実装例

コチラは「H」Stackと繋げるとイメージしやすいように、
アイテムを横に横に積んでいきます。

struct LazyHGridView: View {

    let hGridItem: [GridItem] = [GridItem(.fixed(800))]
    let imageList = ["neko1", "neko2", "neko3", "neko4", "neko5"]

    var body: some View {

        NavigationView {
            ScrollView(.horizontal) {
                LazyHGrid(rows: hGridItem, alignment: .center) {

                    ForEach(0 ..< imageList.count, id: \.self) { index in

                        VStack {
                            // 猫の写真
                            Image(imageList[index])
                                .resizable()
                                .scaledToFit()
                                .frame(height: 200)
                                .foregroundColor(.white)

                            Text("\(index)")
                        }
                    }
                }
                .padding()
            }
            .navigationTitle("LazyHGrid")
        }
    }
}


※RazyGridを使う際の注意点

RazyGridにはデフォルトでスクロール機能は搭載されていません。
スクロールを必要とするデザイン構成の場合はScrollViewを指定する必要があります。
また、ScrollViewはデフォルトだとVertical(縦方向)です。
横にスクロールしたい場合は⬆︎のようにScrollView(.horizontal)としましょう。


■まとめ


以上、RazyGridについて学びました。
GridItem、RazyGrid、それぞれの設定次第でかなり幅広いデザインが構築できるようです。
アプリのデザイン構築において非常に有用な機能だと感じました。
しっかり手に馴染ませて、実際の開発で使いこなしていけるようにしたいと思います✊
では今回はこの辺で。読んでいただきありがとうございました🐱

以上



この記事が気に入ったらサポートをしてみませんか?