環境
Xcode 13.2.1
Swift 5.5.2
Listとは
SwiftUIでは、これまでのUIKitのUITableViewやUICollectionViewを用いたリスト表示を実装したい場合は、List
を使うことで再現ができます。
Listも表示が画面からはみ出た範囲をスクロールできるようになっています。
一番シンプルにListを用いた静的リストの実装は以下になります。Listも表示が画面からはみ出た範囲をスクロールできるようになっています。
var body: some View {
List {
Text("First Item")
Text("Second Item")
Text("Third Item")
}
}

動的リストを作成する
動的にリストを作成した場合は以下のように実装することができます。Identifiable
に準拠したFruitの配列からListを作成しています。
FruitListItemView
は、Listの1つのデータを表示するためのViewです。
struct Fruit: Identifiable {
let id = UUID()
let name: String
}
struct FruitListItemView: View {
var fruit: Fruit
var body: some View {
Text(fruit.name)
}
}
struct ContentView: View {
private var fruits = [
Fruit(name: "Apple"),
Fruit(name: "Orange"),
Fruit(name: "Banana"),
Fruit(name: "peach"),
Fruit(name: "strawberry")
]
var body: some View {
List(fruits) {
FruitListItemView(fruit: fruit)
}
}
}

ForEach
を用いても同じようにリストを作成することができます。
List {
ForEach(fruits) { fruit in
FruitListItemView(fruit: fruit)
}
}
動的と静的両方をListに含ませることもできます。このように自由なリストを作成することができるのでForEach
の方が使う場面は多いと思います。
List {
Text("Dog")
Text("Cat")
ForEach(fruits) { fruit in
FruitListItemView(fruit: fruit)
}
}

Identifiable
に準拠していないデータを用いる場合はid
を指定する必要があります。
private var fruits = [
"Apple",
"Orange",
"Banana",
"peach",
"strawberry",
]
var body: some View {
List {
ForEach(fruits, id: \.self) { fruit in
FruitListItemView(fruit: fruit)
}
}
}
画面遷移をさせる
リスト表示したデータから画面遷移を実装したい場合はNavigationLink
を使用します。
NavigationView {
List {
ForEach(fruits) { fruit in
NavigationLink(destination: SecondView()) {
FruitListItemView(fruit: fruit)
}
}
}
}

NavigationViewの中にListを置いていないと、タップができず画面遷移がされないので注意が必要です。
選択可能なリストにする
単一選択や複数選択ができるようにするにはselection
を設定します。
単一選択
選択した値を格納するためのid
と同じ型のState
変数をListの引数selection
に指定します。
@State private var selectedFruit: UUID?
var body: some View {
NavigationView {
List(selection: $selectedFruit) {
ForEach(fruits) { fruit in
FruitListItemView(fruit: fruit)
}
}
.navigationTitle("Fruits")
.toolbar { EditButton() }
}
}

複数選択
Listの引数selection
に指定する変数をSet
にすることで複数選択ができるようになります。
@State private var selectedFruit = Set<UUID>()

セクションを追加する
表示するViewをSection
で囲むことでセクションを追加できます。header
とfooter
はViewを返すのでTextである必要はありません。ヘッダーのテキストは大文字になるようです。
List {
Section {
ForEach(fruits) { fruit in
FruitListItemView(fruit: fruit, selectedFruit: selectedFruit)
}
} header: {
Text("Fruits")
} footer: {
Text("End")
}
Section {
ForEach(animals, id: \.self) { animal in
Text(animal)
}
} header: {
Text("Animals")
}
}

Listの表示スタイルを変更する
listStyle(_:)
モディファイアを指定することでListの見た目を変更することができます。
List {
}
.listStyle(DefaultListStyle())
指定なし or DefaultListStyle
.listStyle(DefaultListStyle())

InsetListStyle
.listStyle(InsetListStyle())

PlainListStyle
.listStyle(PlainListStyle())

GroupedListStyle
.listStyle(GroupedListStyle())

SidebarListStyle
.listStyle(SidebarListStyle())
