如何在 onTapGesture 中获取本地点击位置?

Igo*_*ich 5 swiftui

有一些渲染图像,需要确定相对于图像的点击位置。看似简单,却找不到答案

  var body: some View {
    VStack {
      Image(uiImage: drawRectangle()) // some rendered image
        .onTapGesture {
          // print(x, y)?
        }
Run Code Online (Sandbox Code Playgroud)

Igo*_*ich 8

找到了这个解决方案:

        .gesture(
            DragGesture(minimumDistance: 0, coordinateSpace: .global)
                .onChanged { value in
                  self.position = value.location
                }
                .onEnded { _ in
                  self.position = .zero
                }
        )
Run Code Online (Sandbox Code Playgroud)

设置minimumDistance: 0将立即调用 onChanged


Riv*_*era 6

我确实尝试使用DragGesturewithminimumDistance: 0但它劫持了我的表格视图的滚动手势。

所以我更喜欢在SwitUI 中使用适当的UITapGestureRecognizer添加到纯透明UIView嵌入中。TappableViewUIViewRepresentable

struct TappableView: UIViewRepresentable
{
    var tapCallback: (UITapGestureRecognizer) -> Void

    typealias UIViewType = UIView

    func makeCoordinator() -> TappableView.Coordinator
    {
        Coordinator(tapCallback: self.tapCallback)
    }

    func makeUIView(context: UIViewRepresentableContext<TappableView>) -> UIView
    {
        let view = UIView()
        view.addGestureRecognizer(UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleTap(sender:))))
        return view
    }

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

    class Coordinator
    {
        var tapCallback: (UITapGestureRecognizer) -> Void

        init(tapCallback: @escaping (UITapGestureRecognizer) -> Void)
        {
            self.tapCallback = tapCallback
        }

        @objc func handleTap(sender: UITapGestureRecognizer)
        {
            self.tapCallback(sender)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后只需将其作为 a.overlay添加到您想要添加点击的 SwiftUI 视图。

.overlay(
    TappableView { gesture in
        // Just use the regular UIKit gesture as you want!
})
Run Code Online (Sandbox Code Playgroud)