SwiftUI中是否可以同时跟踪多个手势?我希望我的一个主视图能够跟踪多个手指一次拖动。
ZStack {
Color.black
.edgesIgnoringSafeArea(.all)
.gesture(DragGesture(minimumDistance: 0)
.onChanged { (value) in
//some logic
}.onEnded { (value) in
//more logic
})
//other code
}
我有这段代码,但是一次只能处理一个拖动手势。如果一根手指在拖动,然后尝试添加另一根,则第一个停止。
我正在尝试实现同时显示多个手指的效果。每个手指同时拖动一个圆圈(每个手指跟随一个圆圈)。
我在Apple文档中看到simultaneous gestures,但这是指使一个手势触发多个块。
答案 0 :(得分:0)
使用UIViewRepresentable的解决方案(How to detect a tap gesture location in SwiftUI?)将起作用。尽管它不是纯粹的swiftUI解决方案(我一直在寻找一种纯粹的swiftUI解决方案,但找不到一个解决方案,并且希望看到一个解决方案)。我已将代码更新为以下代码,您需要更改numberOfTouchPoints = 5,然后使用回调将值显示在视图中。
struct TapView: UIViewRepresentable {
var tappedCallback: (() -> Void)
func makeUIView(context: UIViewRepresentableContext<TapView>) -> TapView.UIViewType {
let v = UIView(frame: .zero)
let gesture = NFingerGestureRecognizer(target: context.coordinator,
action: #selector(Coordinator.tapped))
v.addGestureRecognizer(gesture)
return v
}
class Coordinator: NSObject {
var tappedCallback: (() -> Void)
init(tappedCallback: @escaping (() -> Void)) {
self.tappedCallback = tappedCallback
}
@objc func tapped(gesture:NFingerGestureRecognizer) {
for i in 0..<gesture.numberOfTouches{
print(gesture.location(ofTouch: i, in: gesture.view))
}
self.tappedCallback()
}
}
func makeCoordinator() -> TapView.Coordinator {
return Coordinator(tappedCallback:self.tappedCallback)
}
func updateUIView(_ uiView: UIView,
context: UIViewRepresentableContext<TapView>) {
}
}
class NFingerGestureRecognizer: UIGestureRecognizer {
var numberOfTouchPoints: Int = 2
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
if self.state == .possible {
if (self.numberOfTouches == numberOfTouchPoints){ // we have a two finger interaction starting
self.state = .began
print("two finger drag - Start")
}
} else { // check to see if there are more touchs
if (self.numberOfTouches > numberOfTouchPoints){ // we have a two finger interaction starting
self.state = .failed
print("two finger drag - failed")
}
}
//printInternalTouches()
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
if (self.state != .possible){
self.state = .changed // we are looking for two finger interaction
//printInternalTouches()
print("changed")
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
self.state = .failed
//printInternalTouches()
print("ended")
}
private func printInternalTouches(){
// now print the internal touchUI elements - should be the better solution
print("Internal Locations")
for i in 0..<self.numberOfTouches{
print(self.location(ofTouch: i, in: self.view))
}
}
}
答案 1 :(得分:-1)
我将 Paul 的回答与 Apple 的过时示例相结合,创建了一种检测任意数量触摸的方法。
import Foundation
import UIKit
class NFingerGestureRecognizer: UIGestureRecognizer {
var touchViews = [UITouch:CGPoint]()
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
for touch in touches {
let location = touch.location(in: touch.view)
print("Start: (\(location.x)/\(location.y))")
touchViews[touch] = location
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
for touch in touches {
let oldLocation = touchViews[touch]!
let newLocation = touch.location(in: touch.view)
touchViews[touch] = newLocation
print("Move: (\(oldLocation.x)/\(oldLocation.y)) -> (\(newLocation.x)/\(newLocation.y))")
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
for touch in touches {
let oldLocation = touchViews[touch]!
touchViews.removeValue(forKey: touch)
print("End: (\(oldLocation.x)/\(oldLocation.y))")
}
}
}
更新:
您需要将其包装到 UIViewRepresentable
中才能将其用作 SwiftUI 组件:
struct TapView: UIViewRepresentable {
var tappedCallback: (UITouch, CGPoint?) -> Void
func makeUIView(context: UIViewRepresentableContext<TapView>) -> TapView.UIViewType {
let v = UIView(frame: .zero)
let gesture = NFingerGestureRecognizer(target: context.coordinator, tappedCallback: tappedCallback)
v.addGestureRecognizer(gesture)
return v
}
func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<TapView>) {
// empty
}
}