Gestenbasierte Navigation
Beschreibung
Diese View ersetzt klassische Navigationsbuttons durch Wischgesten nach links und rechts. Nutzer können durch verschiedene Ansichten navigieren, indem sie einfach über den Bildschirm wischen; dabei sorgt haptisches Feedback für ein intuitives und angenehmes Erlebnis.
🔍 Zweck
- Blättern zwischen Seiten wie in einem Onboarding-Prozess
- Navigation in Bildergalerien oder Slideshows ohne Buttons
- Verbesserte Bedienbarkeit für motorisch eingeschränkte Nutzer
- Reduziertes und modernes UI ohne sichtbare Buttons
- Einhandbedienung durch einfache Wischgesten
📄 Codebeispiel
import SwiftUI
struct GestureNavigationView: View {
private let views = [
AnyView(NavigationPageView(title: "Home", color: .blue)),
AnyView(NavigationPageView(title: "Discover", color: .green)),
AnyView(NavigationPageView(title: "Profile", color: .purple))
]
@State private var currentIndex = 0
@Environment(\.colorScheme) private var colorScheme
var body: some View {
ZStack {
views[currentIndex]
.transition(.slide)
.animation(.easeInOut(duration: 0.35), value: currentIndex)
}
// Swipe gesture handling
.gesture(
DragGesture(minimumDistance: 30, coordinateSpace: .local)
.onEnded { value in
let horizontalAmount = value.translation.width
if horizontalAmount < -40 && currentIndex < views.count - 1 {
// Swipe left to go forward
withAnimation {
currentIndex += 1
triggerHaptic(success: true)
}
} else if horizontalAmount > 40 && currentIndex > 0 {
// Swipe right to go back
withAnimation {
currentIndex -= 1
triggerHaptic(success: true)
}
} else {
triggerHaptic(success: false)
}
}
)
// Indicator Dots
VStack {
Spacer()
HStack(spacing: 12) {
ForEach(0..<views.count, id: \.self) { idx in
Circle()
.fill(idx == currentIndex ? Color.primary : Color.primary.opacity(0.2))
.frame(width: idx == currentIndex ? 14 : 8,
height: idx == currentIndex ? 14 : 8)
.scaleEffect(idx == currentIndex ? 1.1 : 1.0)
.animation(.spring(response: 0.3), value: currentIndex)
}
}
.padding(.bottom, 36)
}
}
private func triggerHaptic(success: Bool) {
if success {
let generator = UINotificationFeedbackGenerator()
generator.notificationOccurred(.success)
} else {
let generator = UIImpactFeedbackGenerator(style: .light)
generator.impactOccurred()
}
}
}
struct NavigationPageView: View {
let title: String
let color: Color
var body: some View {
ZStack {
color.opacity(0.13).ignoresSafeArea()
VStack(spacing: 18) {
Image(systemName:
title == "Home" ? "house.fill" :
title == "Discover" ? "sparkles" :
"person.crop.circle.fill"
)
.resizable()
.scaledToFit()
.frame(width: 70, height: 70)
.foregroundStyle(color.opacity(0.8))
Text(title)
.font(.largeTitle.bold())
.foregroundStyle(color.opacity(0.85))
Text("Swipe left or right to navigate")
.font(.body).foregroundStyle(.secondary)
Spacer(minLength: 60)
}
.padding(.top, 80)
}
}
}
#Preview {
GestureNavigationView()
}