Background I’ve been developing an open-source SwiftUI package called SwipeCardUI that provides a basic card-swipe interface. It allows users to drag cards left or right and triggers an action once the card is fully swiped off-screen. However, I’d like to make it behave more like Tinder, where partial swipes, smooth animations, and visual indicators (like/dislike icons, etc.) provide a more engaging user experience.
What I’ve tried
- Offset & Rotation: I currently track the card’s offset in a DragGesture and apply a rotation based on the horizontal distance. This works for simple swipes but feels less “polished” than Tinder.
- Animation: I used SwiftUI’s built-in withAnimation(.spring()) to animate the card flying off-screen, but sometimes the animation doesn’t feel as smooth, especially if the user drags the card slowly or changes direction mid-swipe.
- Partial Swipe States: I attempted to detect the card’s position while dragging to show a “like” or “dislike” icon. However, I’m not sure how best to scale or fade these icons in a way that feels natural.
Minimal Example Here’s a simplified snippet of the code structure (omitting some details for brevity). It demonstrates how I apply offset and rotation:
import SwiftUI
struct SwipeCard: View {
@State private var offset: CGSize = .zero
@State private var rotation: Double = 0
var body: some View {
ZStack {
// Card background
RoundedRectangle(cornerRadius: 16)
.fill(Color.blue)
.frame(width: 300, height: 400)
// Example text or icon
Text("Swipe Me")
.foregroundColor(.white)
.font(.headline)
}
.offset(x: offset.width, y: offset.height * 0.2)
.rotationEffect(.degrees(rotation))
.gesture(
DragGesture()
.onChanged { value in
offset = value.translation
rotation = Double(value.translation.width / 10)
}
.onEnded { value in
// If swipe distance is large enough, animate off-screen
if abs(value.translation.width) > 120 {
withAnimation(.spring()) {
offset.width = value.translation.width > 0 ? 1000 : -1000
rotation = Double(offset.width / 10)
}
// Trigger "like" or "dislike" logic
} else {
// Reset card to center
withAnimation(.spring()) {
offset = .zero
rotation = 0
}
}
}
)
}
}
What I want to achieve • Smooth partial swipes: The user should feel a responsive, elastic effect when dragging, and partial swipes should show a preview of “like” or “dislike” icons. • Advanced animations: Similar to Tinder’s subtle bounces, fade effects, and scaling icons. • Undo/Reset: Possibly re-injecting a card onto the stack if the user regrets a swipe. • Best practices: Unsure if I should use DragGesture + custom transitions, or if there’s a more recommended approach (e.g., using a UIHostingController in UIKit, or a coordinator for more precise gesture tracking).
Question
- How can I replicate Tinder’s advanced swipe behavior—specifically partial acceptance, smooth fling animations, and dynamic icon feedback—in SwiftUI?
- Is there a recommended pattern or known approach for handling more complex drag gestures with mid-swipe states?
- Should I consider a different architecture (e.g., a coordinator or combining UIKit gestures) to achieve finer-grained control over the drag and animation?
I appreciate any suggestions or code examples that can help me improve the user experience in my SwipeCardUI package. If you need more details, let me know, and I’ll provide them. Thank you in advance!
What did you try?
• I used a DragGesture with offset and rotation to animate the card’s movement, referencing my SwipeCardUI project. • I applied withAnimation(.spring()) for the fling-off-screen effect, but it sometimes doesn’t feel as smooth as I’d like. • I attempted to show “like”/“dislike” icons by adjusting opacity based on translation.width, but the transition and partial-swipe feedback aren’t as fluid as Tinder’s. • I tried implementing an “undo” feature by reinserting the card after a swipe, but the card’s position and animation can become inconsistent.
What were you expecting?
• A Tinder-like partial-swipe experience, where icons or labels gradually appear or scale as the user drags the card. • Smoother, more responsive fling animations that handle mid-swipe direction changes gracefully. • A robust “undo” or “revert” function that reintroduces the last swiped card without visual glitches. • Best practices or patterns (e.g., a coordinator or custom transitions) for handling more complex drag gestures and interactive animations in SwiftUI.