【Swift UI】List構造体の使い方!見た目や余白のカスタマイズ
この記事からわかること
- Swift UIのList構造体の使い方
- デザインや余白の変更方法
- 1行ごと区切り線や見た目の変更方法
- リストを複数選択ボタンの実装方法
- 更新インジケータを表示させる方法
- 余白を調整する方法
index
[open]
\ アプリをリリースしました /
環境
- Xcode:16.3
- iOS:18.0
- Swift:5.9
- macOS:Sequoia 15.4
SwiftUIで簡単にリスト形式のビューを実装できるList構造体の使い方をまとめていきます。
List構造体とは?
Swift UIフレームワークで以下のようなリスト形式のビューを簡単に実装できるのがList構造体です。複数のデータを見やすく管理するのに適しており、データ数が多い場合でも自動でスクロールビューにしてくれるのでデータ数を意識する必要がなくなります。
UIKitフレームワークではUITableViewクラスを使用することでリスト形式のビューを実装できますが使用方法は異なります。
使い方
使い方は簡単でList構造体の中にリスト形式で表示させたいビューを渡すだけです。設置するビューはTextでもButtonでもOKです。中に複数のビューを設置することで自動でリスト形式のViewになり、要素が画面の表示エリアからはみ出してもスクロール機能も自動で付与されます。
import SwiftUI
struct ContentView: View {
var body: some View {
List {
Text("要素1")
Text("要素2")
Text("要素3")
}
}
}
Listの中にButtonを設置する
ボタンを設置するとリストの行全体がタップ領域になります。HStackなどで囲うことで1つの行の中に複数のViewを設置できるようになりますが、Buttonを複数設置した場合は行のタップでその中の全てのタップアクションが動作するので注意してください。
List {
Button {
print("ボタン1をタップしたよ")
} label: {
Text("Button1")
}
HStack {
Button {
print("ボタン2をタップしたよ")
} label: {
Text("Button2")
}
Button {
print("ボタン3をタップしたよ")
} label: {
Text("Button3")
}
}
}
ボタンのタップアクションを行タップから伝播せずに、ボタンごとに独立させたい場合はbuttonStyle(.borderless)を使用することで意図した挙動にすることが可能です。
List {
HStack {
Button {
print("ボタン2をタップしたよ")
} label: {
Text("Button2")
}.buttonStyle(.borderless)
Button {
print("ボタン3をタップしたよ")
} label: {
Text("Button3")
}.buttonStyle(.borderless)
}
}
配列のレンジを取得して表示する
List構造体の引数にコレクション型を渡すことで要素を順番に取り出すことが可能です。この場合は中身の要素を一意に識別できるよう必要があるので引数idに\.selfを指定します。これは今回のコレクションがIdentifiableに準拠していない場合に限り、要素がHashableに準拠した型であれば\.selfを指定することができます。
struct ContentView: View {
let langs = ["HTML", "PHP", "Swift"]
var body: some View {
List(langs, id:\.self) { item in
Text(item)
}
}
}
配列.indicesで「0..<配列の要素数」のレンジを取得して、indexを渡す方法でも実装できます。
イニシャライザで配列をデータに使用する
配列内の要素が構造体やクラスなどの場合はIdentifiableプロトコルに準拠させることで引数idを省略できます。
class User:Identifiable {
let id:UUID = UUID()
var name: String = ""
init(name: String) {
self.name = name
}
}
struct ContentView: View {
let users = [User(name: "John"),User(name: "Michael"),User(name: "Johnny")]
var body: some View {
List(users) { user in
Text(user.name)
}
}
}
ForEachで配列をデータに使用する
ForEachを使用することでも配列内の要素を表示させることも可能です。
List {
ForEach(langs, id:\.self) { item in
Text(item)
}
}
リストのスタイルを変更する
List構造体では見た目をカスタマイズするためのモディファイアが数多く用意されています。
listStyleモディファイアを使用することでリストのスタイルを変更できます。引数にはListStyleプロトコルの任意の値を渡します。
struct DefaultListStyle // デフォルト
struct BorderedListStyle // 標準枠 macOS
struct CarouselListStyle // カルーセル watchOS
struct EllipticalListStyle // 楕円 watchOS
struct GroupedListStyle // グループ化 iOS iPadOS Mac Catalyst TVOS
struct InsetListStyle // 差し込み iOS iPadOS macOS Mac Catalyst
struct InsetGroupedListStyle // 差し込みグループ化 iOS iPadOS Mac Catalyst
struct PlainListStyle // プレーン iOS iPadOS Mac Catalyst TVOS watchOS
struct SidebarListStyle // サイドバー iOS iPadOS macOS Mac Catalyst
引数として渡すのはタイププロパティとして定義されている値です。iOSでの例をみていきます。
automatic: DefaultListStyle
通常のスタイルです。左右に余白があります。
.listStyle(.automatic)
grouped: GroupedListStyle
左右の余白がなくなり画面いっぱいに広がります。
.listStyle(.grouped)
inset: InsetListStyle
背景色がなくなり、ビューに差し込まれるスタイルです。
.listStyle(.inset)
見出しをつける
Section構造体を使用することでデータリストに見出しをつけることができます。Section(header:)にヘッダーとして表示させたい文字列を渡します。渡した文字列は強制的に大文字に変換されてしまうようです。
List{
Section(header:Text("datalist")) {
Text("要素1")
Text("要素2")
Text("要素3")
}
}
1行ごとのカスタマイズ
リストの1行1行に対するカスタマイズも柔軟に行えるようにさまざまなモディファイアが用意されています。用途別に見ていきます。これらのメソッドはListではなく中の行Viewに指定します。
区切り線を非表示にする
1行ごとの区切り線を非表示にするにはlistRowSeparatorモディファイアを使用します。
Text("要素1")
.listRowSeparator(.hidden)
区切り線の色を変える
1行ごとの区切り線の色を変更するにはlistRowSeparatorTintモディファイアを使用します。
Text("要素1")
.listRowSeparatorTint(.orange)
中に指定することで1行1行を別々の色に変更することも可能です。
Text("要素1")
.listRowSeparatorTint(.red)
Text("要素2")
.listRowSeparatorTint(.blue)
Text("要素3")
.listRowSeparatorTint(.green)
背景色を変更する
1行ごとの背景色を変更するにはlistRowBackgroundモディファイアを使用します。
.listRowBackground(Color.orange)
行だけでなく全体を変更する方法もあるので詳細は以下の記事を参考にしてください。
余白を調整する
1行ごとの余白を調整更するにはlistRowInsetsモディファイアを使用します。
.listRowInsets(EdgeInsets(top: 30, leading: 10, bottom: 30, trailing: 10))
リストの複数選択するボタンの実装
表示しているデータにチェックボタンを実装し、複数選択可能なリストを作成するには引数selectionにバインディングした変数を渡し、toolbarモディファイアにEditButton構造体を渡します。
struct ContentView: View {
@State private var multiSelection = Set<UUID>()
let users = [User(name: "John"),User(name: "Michael"),User(name: "Johnny")]
var body: some View {
VStack{
NavigationView {
List(users,selection: $multiSelection) { user in
Text(user.name)
}.toolbar { EditButton() }
}
Text("\(multiSelection.count)個")
}
}
}
更新インジケータを表示させる
リストを下にプルダウンした際に更新インジケータを表示させることも可能です。そのためにはrefreshable(action:)を使用して以下のように記述します。
List(users){ user in
Text(user.name)
}
.refreshable {
// await 更新処理
}
リストの1行を長押しでメニューを表示させる
contextMenuを使用して1行を長押しすることでメニューを表示させることが可能です。
struct ContentView: View {
let langs = ["HTML", "PHP", "Swift","kotlin"]
var body: some View {
List(langs.indices, id:\.self){ index in
Text(langs[index])
.contextMenu {
Button {
} label: {
Label("お気に入り", systemImage: "star")
}
}
}
}
}
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。





