高校物理158886 views
高校化学2917196 views
高校日本史190117 views
LaTeX959099 views
ヒストリア286805 views
数学講師2867555 views
中学理科1628254 views
世界の国562102 views
Computer366393 views
小学社会309124 views

スワイプアクション(swipeActions)

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 を指定し、ユーザーに視覚的なフィードバックを与えましょう。