手势干扰图纸拖动

时间:2021-02-11 18:04:06

标签: swiftui

我正在 .sheet 上显示相机预览视图。

我需要检测用户的手指何时触摸预览区域以及用户的手指何时离开预览区域。

我找到的唯一解决方案是这个

  CameraPreview()
    .gesture(DragGesture(minimumDistance: 0)
                          .onChanged { _ in
                            // finger touches
                          }
                          .onEnded { _ in
                            // finger leaves
                          })

但由于此预览显示在工作表上,并且必须通过从上向下拖动工作表来关闭工作表,因此此拖动手势会阻止工作表拖动手势起作用。

有什么想法吗?

注意:我不需要检测拖动。我需要检测视图上的单击,然后在手指离开该视图时接收回调。

1 个答案:

答案 0 :(得分:1)

您需要为此使用 UIViewRepresentable。以下是步骤:

  1. here 创建自定义版本的 AnyGestureRecognizer
class AnyGestureRecognizer: UIGestureRecognizer {
    var onCallback: () -> Void
    var offCallback: () -> Void

    init(target: Any?, onCallback: @escaping () -> Void, offCallback: @escaping () -> Void) {
        self.onCallback = onCallback
        self.offCallback = offCallback
        super.init(target: target, action: nil)
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
        if let touchedView = touches.first?.view, touchedView is UIControl {
            state = .cancelled
            offCallback()
        } else if let touchedView = touches.first?.view as? UITextView, touchedView.isEditable {
            state = .cancelled
            offCallback()
        } else {
            state = .began
            onCallback()
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        state = .ended
        offCallback()
    }

    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent) {
        state = .cancelled
        offCallback()
    }
}
  1. 创建自定义 UIViewRepresentable 视图并将 AnyGestureRecognizer 附加到它:
struct GestureView: UIViewRepresentable {
    var onCallback: () -> Void
    var offCallback: () -> Void

    func makeUIView(context: UIViewRepresentableContext<GestureView>) -> UIView {
        let view = UIView(frame: .zero)
        let gesture = AnyGestureRecognizer(
            target: context.coordinator,
            onCallback: onCallback,
            offCallback: offCallback
        )
        gesture.delegate = context.coordinator
        view.addGestureRecognizer(gesture)
        return view
    }

    func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<GestureView>) {}

    class Coordinator: NSObject {}

    func makeCoordinator() -> GestureView.Coordinator {
        Coordinator()
    }
}

extension GestureView.Coordinator: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        true
    }
}
  1. 将其用作叠加层:
struct ContentView: View {
    var body: some View {
        Color.blue
            .sheet(isPresented: .constant(true)) {
                Color.red
                    .overlay(
                        GestureView(onCallback: { print("start") }, offCallback: { print("end") })
                    )
            }
    }
}