[英]How to implement a left or right DragGesture() that trigger a switch case in SwiftUI?
我在视图中创建了一个 DragGesture,无论用户向左滑动还是向右滑动,它都应该选择一个 @State(Bool)。
问题是只检测到向右滑动。
如何使用 .gesture() 来捕捉用户是在他的屏幕上向左还是向右滑动?
import SwiftUI
struct SwiftUIView: View {
//MARK: Value to change on swipe gesture
@State var swipeRight: Bool
var body: some View {
VStack {
//MARK: Value displayed after user swiped
Text($swipeRight ? "Right" : "Left")
}
.gesture(
DragGesture()
.onChanged { (value) in
//MARK: What is it missing here?
switch value.location.x {
case ...(-0.5):
self.swipeRight = false
print("Swipe Left return false")
case 0.5...:
self.swipeRight = true
print("Swipe Right return true")
default: ()
}
})
}
斯威夫特 5,iOS 13
[Mojtaba Hosseini][1] 提出的改进版本在这里。
[1]: https : //stackoverflow.com/users/5623035/mojtaba-hosseini 。 将枚举和函数放在 ContentView 的主体之前。
enum SwipeHVDirection: String {
case left, right, up, down, none
}
func detectDirection(value: DragGesture.Value) -> SwipeHVDirection {
if value.startLocation.x < value.location.x - 24 {
return .left
}
if value.startLocation.x > value.location.x + 24 {
return .right
}
if value.startLocation.y < value.location.y - 24 {
return .down
}
if value.startLocation.y > value.location.y + 24 {
return .up
}
return .none
}
...
在 DragGesture 中调用它。 在 onEnded 上调用它以阻止它多次触发。
.gesture(DragGesture()
.onEnded { value in
print("value ",value.translation.width)
let direction = self.detectDirection(value: value)
if direction == .left {
// your code here
}
}
)
显然你需要/可以根据需要添加其他方向......
您应该比较旧位置和新位置:
if value.startLocation.x > value.location.x {
print("Swipe Left")
} else {
print("Swipe Right")
}
因此,您的代码的重构版本将是:
struct ContentView: View {
enum SwipeHorizontalDirection: String {
case left, right, none
}
@State var swipeHorizontalDirection: SwipeHorizontalDirection = .none { didSet { print(swipeHorizontalDirection) } }
var body: some View {
VStack {
Text(swipeHorizontalDirection.rawValue)
}
.gesture(
DragGesture()
.onChanged {
if $0.startLocation.x > $0.location.x {
self.swipeHorizontalDirection = .left
} else if $0.startLocation.x == $0.location.x {
self.swipeHorizontalDirection = .none
} else {
self.swipeHorizontalDirection = .right
}
})
}
}
我认为上面的方向是颠倒的? 或者我误解了左右滑动。 无论如何,这是使用视图修饰符的进一步改进。 你可以在 .onSwipe { direction in ... } 到你的观点。
struct SwipeModifier: ViewModifier {
let action: ((UISwipeGestureRecognizer.Direction) -> Void)?
init(perform action: ((UISwipeGestureRecognizer.Direction) -> Void)? = nil) {
self.action = action
}
func body(content: Content) -> some View {
content
.gesture(DragGesture(minimumDistance: 24.0, coordinateSpace: .local)
.onEnded { value in
guard let action = action else {
return
}
if value.startLocation.x > value.location.x {
action(.left)
} else if value.startLocation.x < value.location.x {
action(.right)
} else if value.startLocation.y > value.location.y {
action(.down)
} else if value.startLocation.y < value.location.y {
action(.up)
}
})
}
}
extension View {
public func onSwipe(perform action: ((UISwipeGestureRecognizer.Direction) -> Void)? = nil) -> some View {
return self.modifier(SwipeModifier(perform: action))
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.