Neuerungen in SwiftUI – Teil 4

Swipe Actions

Eines der Highlights in der neuesten SwiftUI-Version stellen Swipe Actions dar. Hierbei handelt es sich um Aktionen, die nach einer Wischgeste über eine Zelle zum Vorschein kommen.

Man kennt diese Aktionen bereits aus vielen Apps, beispielsweise Mail. Wischt man in der Listenansicht von rechts nach links über eine Nachricht, erscheint ein Button mit Papierkorb-Grafik, der das Löschen der gewählten E-Mail ermöglicht.

Mithilfe des neuen swipeActions(edge:allowsFullSwipe:content:)-Modifiers kann man nun selbst auf simple Art und Weise solche Aktionen in eigenen Listen integrieren. Um das zu tun, definiert man über den content-Parameter die Views, die als ausführbare Aktionen nach einer Wischgeste über die Zelle zu sehen sein sollen. Typischerweise nutzt man Button-Instanzen für diesen Zweck.

Ein einfaches Beispiel zum Einsatz des neuen swipeActions(edge:allowsFullSwipe:content:)-Modifiers zeigt das folgende Listing. Darin wird eine Liste mit verschiedenen Gerätenamen angezeigt, die auf einem Array namens devices basiert. Die einzelnen Zellen dieser Liste bestehen aus einer simplen Text-View, die den Namen des Devices anzeigt.

Auf jenen Zellen kommt nun der swipeActions(edge:allowsFullSwipe:content:)-Modifier zum Einsatz. Über den content-Parameter wird ein Button zum Löschen des jeweiligen Devices definiert.

struct Device: Identifiable {
    var id = UUID()
    var name: String
}

struct ContentView: View {
    @State private var devices = [
        Device(name: "MacBook Pro 16"),
        Device(name: "iMac Pro"),
        Device(name: "iPhone 12 Pro Max"),
        Device(name: "iPad Pro 12,9"),
        Device(name: "Apple Watch Series 5"),
        Device(name: "Apple TV 4K")
    ]
    
    var body: some View {
        List(devices) { device in
            Text(device.name)
                .swipeActions {
                    Button {
                        delete(device: device)
                    } label: {
                        Label("Delete", systemImage: "trash.fill")
                    }
                    .tint(.red)
                }
        }
    }
    
    private func delete(device: Device) {
        devices.removeAll(where: { $0.id == device.id })
    }
}

Wischt man nun von rechts nach links über eine Zelle, erscheint dieser Löschen-Button. Wischt man weiter nach rechts oder betätigt den Button, wird die zugehörige Aktion (sprich die Löschung des Devices) ausgeführt.

Mithilfe eines neuen Modifiers lassen sich Swipe Actions nun ganz einfach in SwiftUI umsetzen.
Mithilfe eines neuen Modifiers lassen sich Swipe Actions nun ganz einfach in SwiftUI umsetzen.

Auf diese Art und Weise lassen sich auch mehrere Buttons als Swipe Actions umsetzen. Diese Buttons tauchen dann nebeneinander auf, nachdem die entsprechende Wischgeste auf einer Zelle ausgeführt wurde.

Erweiterte Konfiguration

Wie man anhand des Namens des swipeActions(edge:allowsFullSwipe:content:)-Modifiers bereits sehen kann, stehen mit edge und allowsFullSwipe zwei weitere Parameter zur Verfügung, mit denen sich Swipe Actions konfigurieren lassen. Man kann generell auf ihren Einsatz verzichten (so wie das im vorherigen Beispiel zu sehen war), da beide über einen Standardwert verfügen.

edge steuert die Position der Buttons und damit auch, in welche Richtung der Nutzer über eine Zelle wischen muss, um die zugehörigen Swipe Actions sichtbar zu machen. Der Standardparameter entspricht .trailing, in unserem Fall also dem rechten Rand. Wollt ihr hingegen Swipe Actions am linken Rand einer Zelle unterbringen, die dann entsprechend auch per Wischgeste von links nach rechts abgerufen werden, setzt ihr als Wert für den edge-Parameter .leading.

Mithilfe von allowsFullSwipe steuert ihr darüber hinaus, ob die erste Swipe Action automatisch ausgeführt wird, wenn der Nutzer die Wischbewegung fortsetzt. Standardmäßig ist diese Option aktiv (true), ihr könnt sie mittels Übergabe von false aber auch deaktivieren.

Ergänzend zum vorherigen Beispiel zeigt das nachfolgende Listing den Einsatz eines zweiten swipeActions(edge:allowsFullSwipe:content:)-Modifiers, der auf alle verfügbaren Parameter zurückgreift und eine weitere Aktion am linken Rand der Zellen unterbringt.

struct Device: Identifiable {
    var id = UUID()
    var name: String
}

struct ContentView: View {
    @State private var devices = [
        Device(name: "MacBook Pro 16"),
        Device(name: "iMac Pro"),
        Device(name: "iPhone 12 Pro Max"),
        Device(name: "iPad Pro 12,9"),
        Device(name: "Apple Watch Series 5"),
        Device(name: "Apple TV 4K")
    ]
    
    var body: some View {
        List(devices) { device in
            Text(device.name)
                .swipeActions {
                    Button {
                        delete(device: device)
                    } label: {
                        Label("Delete", systemImage: "trash.fill")
                    }
                    .tint(.red)
                }
                .swipeActions(edge: .leading, allowsFullSwipe: false) {
                    Button {
                        // Mark device as Favorite
                    } label: {
                        Label("Favorite", systemImage: "star.fill")
                    }
                    .tint(.yellow)
                }
        }
    }
    
    private func delete(device: Device) {
        devices.removeAll(where: { $0.id == device.id })
    }
}

Fazit

Swipe Actions sind eine wunderbare Ergänzung innerhalb des SwiftUI-Frameworks. Endlich ist es mit minimalen Aufwand möglich, Listenzellen um zusätzliche Aktionen zu ergänzen, die Nutzer via Wischgeste aufrufen können; genau so, wie man es schon seit langem von einer großen Zahl von Apps her kennt.

Die entsprechende API ist Apple wunderbar gelungen und ermöglicht es, mit nur wenigen Zeilen Code bestehende Zellen um Swipe Actions zu erweitern. Hier zeigt SwiftUI wieder einmal ganz deutlich, wie leicht sich ansonsten komplexe Funktionen nun umsetzen lassen.

Die neuen Swipe Actions stehen ab macOS Monterey 12, iOS/iPadOS 15 und watchOS 8 zur Verfügung.

Euer Thomas


Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert