【SwiftUI】リスト表示(一覧画面)の使い方

本記事では、リスト表示の基本的な使い方とテキスト・画像・ラベルなどをリスト内に配置して表示する方法、配列のデータをリスト表示する方法について説明していきます。

リストの配置

SwiftUIのリストは、中に格納されたテキストなどの各要素を整列させて表示させることができ、並べ替えたり指定した要素を検索することもでき、多くのアプリに採用されている機能になります。

Vstack内に配置すること と同じようにList内に配置したオブジェクトなどの要素は全てリストとして扱われます。

List{}を使用してリストを作成することができます。プロジェクト作成時にVstackが表示されているの部分をList{}に置き換えます。

struct ContentView: View {
    var body: some View {
        List{
            
        }
    }
}

要素の配置

List{}の中にテキスト/画像/ラベルなどを入れて表示する際の実際のソースコードと表示内容を解説していきます。

テキスト/ラベル/画像などはそれぞれ一つのリストとして列挙していくことができ、様々な要素をリストで表現することが可能です。

テキスト&ラベルを配置

まずはテキストを配置していきます。単純にList{}内にTextやLabelを配置していくだけです。様々なメモアプリであるような一覧の画面が非常に簡単に作成できました。

var body: some View {
        List{
            Text("テキスト1")
            Text("テキスト2")
            Text("テキスト3")
            Text("テキスト4")
            Text("テキスト5")
            Label("ラベル1", systemImage: "figure.badminton")
            Label("ラベル2", systemImage: "figure.baseball")
            Label("ラベル3", systemImage: "figure.cooldown")
            Label("ラベル4", systemImage: "figure.core.training")
            Label("ラベル5", systemImage: "figure.socialdance")
        }
    }

画面表示

画像を配置

リスト内には画像も配置することができます。画像をXcodeプロジェクト内に配置する方法については以下の記事でご紹介していきますのでご確認ください。

画像をXcodeプロジェクト内にアップロードしたら、Image(“画像名”)で画像をList内のに配置していきます。先ほどのテキストの下に、縦横比を変えずにList{}の横幅を上限とするようImage().scaleToFit()を設定した画像を追加していきます。

var body: some View {
        List{
            Text("テキスト1")
            Text("テキスト2")
            Text("テキスト3")
            Text("テキスト4")
            Text("テキスト5")
            Label("ラベル1", systemImage: "figure.badminton")
            Label("ラベル2", systemImage: "figure.baseball")
            Label("ラベル3", systemImage: "figure.cooldown")
            Label("ラベル4", systemImage: "figure.core.training")
            Label("ラベル5", systemImage: "figure.socialdance")
            Image("beach-free1")
                .resizable().scaledToFit()
            Image("beach-free2")
                .resizable().scaledToFit()
            Image("sea-free")
                .resizable().scaledToFit()
        }
    }

画面表示

リストの行の高さを揃える

画像を設定する際の例を見ていただくとわかるように、画像サイズによってリストの各列の高さが変わってきてしまいます。

リストの高さは、List{}.environment(\.defaultMinListRowHeight, 高さ)を設定することで均一に揃えることができます。以下の例では、各行の高さを100と指定することで画像を設定しても高さが崩れることなく表示されることが確認できます。

var body: some View {
        List{
            Text("テキスト1")
            Text("テキスト2")
            Text("テキスト3")
            Text("テキスト4")
            Text("テキスト5")
            Label("ラベル1", systemImage: "figure.badminton")
            Label("ラベル2", systemImage: "figure.baseball")
            Label("ラベル3", systemImage: "figure.cooldown")
            Label("ラベル4", systemImage: "figure.core.training")
            Label("ラベル5", systemImage: "figure.socialdance")
            Image("beach-free1")
                .resizable().scaledToFit().frame(height: 100)
            Image("beach-free2")
                .resizable().scaledToFit().frame(height: 100)
            Image("sea-free")
                .resizable().scaledToFit().frame(height: 100)
        }.environment(\.defaultMinListRowHeight, 100)
    }

画面表示

各画像は、縦横比を崩さずに高さを合わせるように設定しているため、横幅がバラバラに見えてしまっていますので、お好みで横幅も指定してトリミングなどを行うといいかもしれません。

画像の加工方法については以下の記事で解説していますので見に行ってみてください。

リストに名前をつける

リスト表示を使用する際には、そのリストが何のリストであるかを表すためにタイトルをつけることができます。リストにタイトルをつける際には以下の2つの手順が必要です。

  1. List{}をNavigationView{}で囲む。
  2. Navigation{}内のList{}に.navigationTitle()をつけてタイトルを付与する。

NavigationView{}は、List{}を囲むことで、タイトルをつけることができる他にリストをクリックした際に別のページに移動するなど動作を実現するために必要な機能となります。

var body: some View {
        NavigationView{
            List{
                Text("テキスト1")
                Text("テキスト2")
                Text("テキスト3")
                Text("テキスト4")
                Text("テキスト5")
                Label("ラベル1", systemImage: "figure.badminton")
                Label("ラベル2", systemImage: "figure.baseball")
                Label("ラベル3", systemImage: "figure.cooldown")
                Label("ラベル4", systemImage: "figure.core.training")
                Label("ラベル5", systemImage: "figure.socialdance")
                Image("beach-free1")
                    .resizable().scaledToFit().frame(height: 100)
                Image("beach-free2")
                    .resizable().scaledToFit().frame(height: 100)
                Image("sea-free")
                    .resizable().scaledToFit().frame(height: 100)
            }.environment(\.defaultMinListRowHeight, 100)
                .navigationTitle("リストのタイトル")
            
        }
    }

画面表示

配列の値をリストとして表示する

ここまででリスト表示を行う方法を解説してきましたが、大量の似たようなリストを用意したい場合にはリストの要素一つ一つを書いていては労力がかかるだけでなく、ソースコードの可読性も悪くなります。

そこで、リストの各要素に配列の中身を表示していく方法をご紹介します。手順は2つあり、簡単には以下の通りです。

手順1

  1. データの入った配列を用意する。
  2. List(){}を使用して引数として配列を渡す。

手順2

  1. データの入った配列を用意する。
  2. List{}を用意する
  3. List{}内でForEach文を利用して配列をループして

手順2の中で使用しているような配列をループして中の値を操作する処理として、for,while,forEachなどの方法も挙げられますが、これら4つの方法の中ではForEach以外の方法ではviewを作成することはできませんので、ご注意ください。

手順1のコード

var listContents = ["テキスト1", "テキスト2", "テキスト3", "テキスト4", "テキスト5"]

struct ContentView: View {
    var body: some View {
        List(listContents, id: \.self){ content in
            Text(content)
        }
    }
}

画面表示

手順2のコード

var listContents = ["テキスト1", "テキスト2", "テキスト3", "テキスト4", "テキスト5"]

struct ContentView: View {
    var body: some View {
        List{
            ForEach(listContents, id: \.self) { listContent in
                Text(listContent)
            }
        }
    }
}

画面表示

リストを複数のセクションに分割する

ここまで、リストを1つの塊として扱ってきましたが、一つの画面内でリストを複数のグループに分割してそれぞれに名前をつけて扱うこともできます。これをリスト内の要素を複数セクションに分割すると表現することができます。

リストを複数セクションに分割して、テキスト/ラベル/イメージをそれぞれ表示します。分割するためにはList{}内にSection(){}を分割する分だけ追加してその中に要素を追加していきます。

以下に示す例ではそれぞれの配列を用意して各セクション内でForEachにて要素を出力しています。

また、Section(){}へのパラメータとして、header:”タイトル名”でタイトルを指定することもできます。

var listContents = ["テキスト1", "テキスト2", "テキスト3", "テキスト4", "テキスト5"]
var listLabels = ["figure.badminton","figure.baseball","figure.cooldown","figure.core.training","figure.socialdance"]
var listImages = ["beach-free1","beach-free2","sea-free"]

struct ContentView: View {
    var body: some View {
        List{
            Section(header: Text("テキスト")){
                ForEach(listContents, id: \.self) { listContent in
                    Text(listContent)
                }
            }
            Section(header: Text("ラベル")){
                ForEach(listLabels, id: \.self) { listLabel in
                    Label("ラベル", systemImage: listLabel)
                }
            }
            Section(header: Text("イメージ")){
                ForEach(listImages, id: \.self) { listImage in
                    Image(listImage)
                        .resizable().scaledToFit().frame(height: 100)
                        
                }
            }
        }
    }
}

表示画面

最後に

本記事では、SwiftUI でのリストの基本的な使い方を解説してきました。他にもSwiftUIでの基本的な使い方について色々解説していますのでぜひご覧になっていってください。