はじめに
こんにちは、iOSアプリ開発グループの神山です。
SwiftUIについて絶賛勉強中なのですが、今回はUIKitでのUITableViewに相当するListの作成方法についてまとめてみました。
List
Listはデータの一覧を表示するのに適したコンポーネントです。
静的なデータを表示するだけなら以下のようなコードで簡単に表示することができます。
struct ContentView: View { var body: some View { List { Text("りんご") Text("ぶどう") Text("もも") Text("いちご") } } } |
動的なデータの場合は ForEachを使うことで一覧表示することができます。
struct ContentView: View { private let fruits = ["りんご", "ぶどう", "もも", "いちご", "マンゴー", "パイナップル"] var body: some View { List { ForEach(fruits, id: \.self) { fruit in Text(fruit) } } } } |
ForEachを使用せずにListのみで表示することもできますが、行の削除や行の入れ替えの処理はできないため、単純な動的なデータを表示したい場合のみに使用できます。
struct ContentView: View { private let fruits = ["りんご", "ぶどう", "もも", "いちご"] var body: some View { List(fruits, id: \.self) { fruit in Text(fruit) } } } |
行の削除や行の入れ替えは ForEachが準拠している DynamicViewContent内の onDelete(perform:), onMove(perform:)を使用します。
struct ContentView: View { @State private var fruits = ["りんご", "ぶどう", "もも", "いちご", "マンゴー"] var body: some View { VStack { List { ForEach(fruits, id: \.self) { fruit in Text(fruit) } .onMove { indexSet, index in fruits.move(fromOffsets: indexSet, toOffset: index) } .onDelete { indexSet in fruits.remove(atOffsets: indexSet) } } EditButton() .padding() } } } |
Listのカスタマイズ
Sectionを使用することでListのグループ化を簡単に行うことができます。
以下では
Sectionを使用してヘッダー、フッターをつけたListを作成しました。
struct ContentView: View { private let fruits = ["りんご", "ぶどう", "もも", "いちご", "マンゴー", "パイナップル"] private let fishes = ["まぐろ", "かつお", "さんま", "さけ"] var body: some View { List { Section(header: Text("果物")) { ForEach(fruits, id: \.self) { fruit in Text(fruit) } } Section(header: Text("魚"), footer: Text("さかなに関するフッター")) { ForEach(fishes, id: \.self) { fish in Text(fish) } } } } } |
Modifier
List、Sectionに関するModifierをご紹介します。
- listStyle(_: ListStyle) Listの表示スタイルの指定
automatic | plain | grouped |
---|---|---|
inset | insetGrouped | sidebar |
---|---|---|
- listRowSeparator(visibility, edges: VerticalEdge), listSectionSeparator(visibility, edges: VerticalEdge) セパレーターの表示可否の指定
visible(default) | hidden |
---|---|
- listRowSeparatorTint(color, edges: VerticalEdge), listSectionsSeparatorTint(color, edges: VerticalEdge) セパレーターの色の指定
red | green |
---|---|
- listRowBackground(_: View) 背景の指定
blue | yellow |
---|---|
- listRowInsets(_: EdgeInsets) 余白の指定
top10 | left10 | bottom10 | right10 |
---|---|---|---|
Listのタップ処理
List内のアイテムにタップ処理を追加するには onTapGesture()のModifierを使用します。
Listをタップした際に画像とテキストを更新するようにしてみます。
struct Fish: Hashable { var isExpire: Bool = false var name: String } struct ContentView: View { @State private var fishes: [Fish] = [ Fish(name: "まぐろ"), Fish(name: "かつお"), Fish(name: "さんま"), Fish(name: "さけ") ] var body: some View { List { Section(header: Text("魚")) { ForEach(0..<fishes.count, id: \.self) { index in Label( fishes[index].isExpire ? "\(fishes[index].name): 賞味期限切れ" : fishes[index].name, systemImage: fishes[index].isExpire ? "trash.circle.fill" : "hand.thumbsup.fill" ) .onTapGesture { fishes[index].isExpire.toggle() } } } } } } |
タップ前 | タップ後 |
---|---|
また、 contentShape(_:)と Spacer()を組み合わせることでタップ領域を全体に広げることができます。
var body: some View { List { Section(header: Text("魚")) { ForEach(0..<fishes.count, id: \.self) { index in HStack { // 追加 Label( fishes[index].isExpire ? "\(fishes[index].name): 賞味期限切れ" : fishes[index].name, systemImage: fishes[index].isExpire ? "trash.circle.fill" : "hand.thumbsup.fill" ) Spacer() // 追加 } .contentShape(Rectangle()) // 追加 .onTapGesture { fishes[index].isExpire.toggle() } } } } } |
さいごに
一覧表示するために使用されるListは、どのようなアプリを作る際でも使う可能性が高いコンポーネントでもあるため、上手く使いこなせるように今後も調べていこうと思います。
最後まで記事を読んで頂き、ありがとうございました。
参考文献
この記事を書いた人
- iOSエンジニアです。
最近書いた記事
- 2023.05.09iOSの証明書関連をイラストで理解する
- 2022.12.19【Swift】Widgetの作り方 〜iOS 16対応版〜
- 2022.09.26【Swift】 Combine Publisher Operatorsまとめ
- 2022.09.26【Swift】 Combineを使用するメリットについて考えてみる