iPhoneのメールアプリで、メッセージを左右にスワイプして削除やアーカイブができる機能を使ったことはありませんか?
SwiftUIのswipeActions
を使えば、このような直感的な操作を簡単に実装できます。本記事では、SwiftUI初心者の方でもわかるように、swipeActions
の基本から実践的な使い方まで詳しく解説します。
目次
swipeActionsとは?
swipeActions
は、SwiftUIでリストやテーブルの行をスワイプした際に表示されるアクションボタンを定義するためのモディファイアです。
主な特徴
- iOS 15以降で利用可能
- 左右両方向のスワイプに対応
- 複数のアクションボタンを配置可能
- カスタマイズ性が高い
できること
- メッセージの削除
- アイテムのお気に入り登録
- 編集画面への遷移
- アーカイブや既読処理など
基本的な使い方
最もシンプルな実装例から見ていきましょう。
import SwiftUI
struct ContentView: View {
@State private var items = ["リンゴ", "バナナ", "オレンジ"]
var body: some View {
NavigationView {
List {
ForEach(items, id: \.self) { item in
Text(item)
.swipeActions {
Button(role: .destructive) {
// 削除処理
items.removeAll { $0 == item }
} label: {
Label("削除", systemImage: "trash")
}
}
}
}
.navigationTitle("フルーツリスト")
}
}
}
コードの解説
@State
で配列を管理List
とForEach
でリスト表示.swipeActions
モディファイアを追加Button(role: .destructive)
で赤い削除ボタンを作成Label
でアイコンとテキストを表示
左右両方向のスワイプを実装する
edge
パラメータを使うことで、左右それぞれに異なるアクションを設定できます。
Text(item)
.swipeActions(edge: .trailing) {
// 右から左へスワイプ(trailing)
Button(role: .destructive) {
deleteItem(item)
} label: {
Label("削除", systemImage: "trash")
}
}
.swipeActions(edge: .leading) {
// 左から右へスワイプ(leading)
Button {
favoriteItem(item)
} label: {
Label("お気に入り", systemImage: "star.fill")
}
.tint(.yellow)
}
edgeパラメータの種類
.trailing
: 右から左へスワイプ(デフォルト).leading
: 左から右へスワイプ
複数のアクションボタンを配置する
1つのスワイプに複数のボタンを配置することも可能です。
.swipeActions {
Button(role: .destructive) {
deleteItem(item)
} label: {
Label("削除", systemImage: "trash")
}
Button {
editItem(item)
} label: {
Label("編集", systemImage: "pencil")
}
.tint(.blue)
Button {
shareItem(item)
} label: {
Label("共有", systemImage: "square.and.arrow.up")
}
.tint(.green)
}
ボタンは右から順に表示されます。
ボタンの色をカスタマイズする
roleによる色の指定
// 赤色(削除用)
Button(role: .destructive) { } label: { Text("削除") }
// グレー
Button(role: .cancel) { } label: { Text("キャンセル") }
// デフォルト(青色)
Button { } label: { Text("通常") }
tintによる色の指定
Button {
// 処理
} label: {
Label("お気に入り", systemImage: "star.fill")
}
.tint(.yellow) // 任意の色を指定
フルスワイプの動作を制御する
デフォルトでは、完全にスワイプすると最初のアクションが自動実行されます。これを無効にするにはallowsFullSwipe
を使います。
.swipeActions(allowsFullSwipe: false) {
Button(role: .destructive) {
deleteItem(item)
} label: {
Label("削除", systemImage: "trash")
}
}
allowsFullSwipe: false
を設定すると、誤操作を防げます。
実践的な実装例
ToDoアプリ風の実装
import SwiftUI
struct Task: Identifiable {
let id = UUID()
var title: String
var isCompleted: Bool = false
var isFavorite: Bool = false
}
struct ToDoListView: View {
@State private var tasks = [
Task(title: "買い物に行く"),
Task(title: "レポートを書く"),
Task(title: "ジムに行く")
]
var body: some View {
NavigationView {
List {
ForEach($tasks) { $task in
HStack {
Image(systemName: task.isCompleted ? "checkmark.circle.fill" : "circle")
.foregroundColor(task.isCompleted ? .green : .gray)
Text(task.title)
.strikethrough(task.isCompleted)
Spacer()
if task.isFavorite {
Image(systemName: "star.fill")
.foregroundColor(.yellow)
}
}
.contentShape(Rectangle())
.onTapGesture {
task.isCompleted.toggle()
}
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
Button(role: .destructive) {
tasks.removeAll { $0.id == task.id }
} label: {
Label("削除", systemImage: "trash")
}
Button {
// 編集処理
} label: {
Label("編集", systemImage: "pencil")
}
.tint(.blue)
}
.swipeActions(edge: .leading) {
Button {
task.isFavorite.toggle()
} label: {
Label(
task.isFavorite ? "解除" : "お気に入り",
systemImage: task.isFavorite ? "star.slash" : "star.fill"
)
}
.tint(.yellow)
}
}
}
.navigationTitle("ToDoリスト")
}
}
}
この実装では以下の機能を実現しています。
- タップで完了/未完了を切り替え
- 右スワイプで削除・編集
- 左スワイプでお気に入り登録
- お気に入りアイテムには星マークを表示
よくある質問(FAQ)
Q1. iOS 15未満で使いたい場合は?
iOS 15未満ではswipeActions
が使えません。代わりに以下の方法を検討してください。
// iOS 13以降で使える方法
.onDelete { indexSet in
items.remove(atOffsets: indexSet)
}
Q2. アニメーションをカスタマイズできる?
swipeActions
自体のアニメーションは自動で最適化されているため、カスタマイズはできません。ボタン押下後の処理内でアニメーションを追加することは可能です。
Button {
withAnimation {
// アニメーション付きで処理
items.removeAll { $0.id == item.id }
}
} label: {
Label("削除", systemImage: "trash")
}
Q3. スワイプの感度を調整できる?
スワイプの感度はシステムが自動で管理しているため、開発者側で調整することはできません。
まとめ
swipeActions
を使えば、以下のような直感的なUIを簡単に実装できます。
- 左右両方向のスワイプアクション
- 複数ボタンの配置
- カスタマイズ可能な色とアイコン
- フルスワイプの制御
初心者の方は、まず基本的な削除機能から実装してみて、徐々に複雑な機能を追加していくことをおすすめします。