Little bit late to this, but here's another implementation which uses OptionSet to make its use a bit more like various other SwiftUI components -
struct Swipe: OptionSet, Equatable {
init(rawValue: Int) {
self.rawValue = rawValue
}
let rawValue: Int
fileprivate var swiped: ((DragGesture.Value, Double) -> Bool) = { _, _ in false } // prevents a crash if someone creates a swipe directly using the init
private static let sensitivityFactor: Double = 400 // a fairly arbitrary figure which gives a reasonable response
static var left: Swipe {
var swipe = Swipe(rawValue: 1 << 0)
swipe.swiped = { value, sensitivity in
value.translation.width < 0 && value.predictedEndTranslation.width < sensitivity * sensitivityFactor
}
return swipe
}
static var right: Swipe {
var swipe = Swipe(rawValue: 1 << 1)
swipe.swiped = { value, sensitivity in
value.translation.width > 0 && value.predictedEndTranslation.width > sensitivity * sensitivityFactor
}
return swipe
}
static var up: Swipe {
var swipe = Swipe(rawValue: 1 << 2)
swipe.swiped = { value, sensitivity in
value.translation.height < 0 && value.predictedEndTranslation.height < sensitivity * sensitivityFactor
}
return swipe
}
static var down: Swipe {
var swipe = Swipe(rawValue: 1 << 3)
swipe.swiped = { value, sensitivity in
value.translation.height > 0 && value.predictedEndTranslation.height > sensitivity * sensitivityFactor
}
return swipe
}
static var all: Swipe {
[.left, .right, .up, .down]
}
private static var allCases: [Swipe] = [.left, .right, .up, .down]
fileprivate var array: [Swipe] {
Swipe.allCases.filter { self.contains($0) }
}
}
extension View {
func swipe(_ swipe: Swipe, sensitivity: Double = 1, action: @escaping (Swipe) -> ()) -> some View {
return gesture(DragGesture(minimumDistance: 30, coordinateSpace: .local)
.onEnded { value in
swipe.array.forEach { swipe in
if swipe.swiped(value, sensitivity) {
action(swipe)
}
}
}
)
}
}
In a SwiftUI view -
HStack {
// content
}
.swipe([.left, .right]) { swipe in // could also be swipe(.left) or swipe(.all), etc
doSomething(with: swipe)
}
Obviously the logic for detecting swipes is a bit basic, but that's easy enough to tailor to your requirements.