List の行をスワイプしてアクションボタンを表示する機能は、iOS アプリで広く使われている UI パターンです。SwiftUI では swipeActions モディファイアで簡単に実装できます。
基本的なスワイプアクション
swipeActions モディファイアを行に適用することで、スワイプ時に表示されるボタンを定義できます。
struct ContentView: View { @State private var items = ["項目1", "項目2", "項目3"] var body: some View { List { ForEach(items, id: \.self) { item in Text(item) .swipeActions { Button(role: .destructive) { // 削除処理 } label: { Label("削除", systemImage: "trash") } } } } } }
デフォルトでは右から左へのスワイプ(trailing 側)でアクションが表示されます。
スワイプ方向の指定
edge パラメータで、左右どちらからスワイプしたときにアクションを表示するか指定できます。
Text(item) .swipeActions(edge: .leading) { Button { // ピン留め処理 } label: { Label("ピン留め", systemImage: "pin") } .tint(.yellow) } .swipeActions(edge: .trailing) { Button(role: .destructive) { // 削除処理 } label: { Label("削除", systemImage: "trash") } }
edge: .leading
左から右へスワイプしたとき(行の左側にボタン表示)
edge: .trailing
右から左へスワイプしたとき(行の右側にボタン表示、デフォルト)
複数のアクションボタン
複数のボタンを並べることも可能です。
Text(item) .swipeActions(edge: .trailing, allowsFullSwipe: false) { Button(role: .destructive) { // 削除 } label: { Label("削除", systemImage: "trash") } Button { // アーカイブ } label: { Label("アーカイブ", systemImage: "archivebox") } .tint(.blue) Button { // フラグ } label: { Label("フラグ", systemImage: "flag") } .tint(.orange) }
allowsFullSwipe: false を指定すると、フルスワイプによる自動実行を無効にできます。
ボタンの色(tint)
tint モディファイアでボタンの背景色を変更します。role: .destructive を指定した場合は自動的に赤になります。
Button { // 処理 } label: { Label("お気に入り", systemImage: "heart") } .tint(.pink)
実践的な例:Todo リスト
struct Task: Identifiable { let id = UUID() var title: String var isCompleted: Bool } struct TodoListView: View { @State private var tasks = [ Task(title: "買い物", isCompleted: false), Task(title: "掃除", isCompleted: true), Task(title: "洗濯", isCompleted: false) ] var body: some View { List { ForEach($tasks) { $task in HStack { Image(systemName: task.isCompleted ? "checkmark.circle.fill" : "circle") .foregroundColor(task.isCompleted ? .green : .gray) Text(task.title) } .swipeActions(edge: .leading) { Button { task.isCompleted.toggle() } label: { Label( task.isCompleted ? "未完了に戻す" : "完了", systemImage: task.isCompleted ? "arrow.uturn.backward" : "checkmark" ) } .tint(task.isCompleted ? .orange : .green) } .swipeActions(edge: .trailing) { Button(role: .destructive) { tasks.removeAll { $0.id == task.id } } label: { Label("削除", systemImage: "trash") } } } } } }
swipeActions は直感的な操作を可能にする重要な UI 要素です。削除のような破壊的な操作には role: .destructive を指定し、ユーザーに視覚的なフィードバックを与えましょう。