我目前正在尝试使用SwiftUI构建一个与Procreate相似的应用程序(当然要简单得多 ;) )。
我目前遇到的最大问题是导航。我希望使用两指滑动手势在画布上进行导航。我已经进行了大量的研究,但还没有找到如何在SwiftUI手势中实现这一点的解决方案。
我目前的解决方案是使用UIViewRepresentable和附加的手势监听器。不幸的是,这会破坏所有子视图中的手势识别器(而且有很多子视图,我需要它们全部)。
当前的实现代码如下:
struct TwoFingerNavigationView: UIViewRepresentable {
var draggedCallback: ((CGPoint) -> Void)
var dragEndedCallback: (() -> Void)
class Coordinator: NSObject {
var draggedCallback: ((CGPoint) -> Void)
var dragEndedCallback: (() -> Void)
init(draggedCallback: @escaping ((CGPoint) -> Void),
dragEndedCallback: @escaping (() -> Void)) {
self.draggedCallback = draggedCallback
self.dragEndedCallback = dragEndedCallback
}
@objc func dragged(gesture: UIPanGestureRecognizer) {
if gesture.state == .ended {
self.dragEndedCallback()
} else {
self.draggedCallback(gesture.translation(in: gesture.view))
}
}
}
func makeUIView(context: UIViewRepresentableContext<TwoFingerNavigationView>) -> TwoFingerNavigationView.UIViewType {
let view = UIView(frame: .zero)
let gesture = UIPanGestureRecognizer(target: context.coordinator,
action: #selector(Coordinator.dragged))
gesture.minimumNumberOfTouches = 2
gesture.maximumNumberOfTouches = 2
view.addGestureRecognizer(gesture)
return view
}
func makeCoordinator() -> TwoFingerNavigationView.Coordinator {
return Coordinator(draggedCallback: self.draggedCallback,
dragEndedCallback: self.dragEndedCallback)
}
func updateUIView(_ uiView: UIView,
context: UIViewRepresentableContext<TwoFingerNavigationView>) {
}
}
使用方法如下:
ZStack {
OtherView()
.gesture() // This will break with this "hack"
TwoFingerNavigationView(draggedCallback: { translation in
var newLocation = startLocation ?? location
newLocation.x += (translation.x / scale)
newLocation.y += (translation.y / scale)
self.location = newLocation
}, dragEndedCallback: {
startLocation = location
})
}
有没有人有想法,如何使用SwiftUI手势识别器复制功能,或使其在不破坏所有子元素手势的情况下与UIKit实现一起工作?
非常感谢任何帮助和指针!