0

Because I need to know whether user taps with finger or pencil, I had to create a UIViewRepresentable with a UITapGestureRecognizer. Everything works fine when this View is used with other SwiftUI views. But when stack 2 of this view, and I clip the top one, the other one never catches any tap event.

enter image description here

Here is my custom view:

struct UIKitView: UIViewRepresentable {
  let color: UIColor
  
  func makeUIView(context: Context) -> UIView {
    let view = UIView()
    view.backgroundColor = color
    let tapGesture = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleTap(gesture:)))
    view.addGestureRecognizer(tapGesture)
    return view
  }

  func updateUIView(_ uiView: UIView, context: Context) {  }

  func makeCoordinator() -> Coordinator {
    Coordinator(color: color)
  }

  class Coordinator: NSObject {
    let color: UIColor

    init(color: UIColor) {
      self.color = color
    }

    @objc func handleTap(gesture: UITapGestureRecognizer) {
      print("Tapped in \(color == .yellow ? "yellow" : "red")")
    }
  }
}

And here how it is used in SwiftUI View:

ZStack {
  UIKitView(color: .yellow)
  UIKitView(color: .red)
    .clipShape(Circle())) // not required, just visual   
    .contentShape(Circle()))
}

The tap is always catched by the red view.

Then I've overriden the hitTest() function of my UIVIewRepresentable to check if the tap is inside the clipîng shape. The tap is then detected in the red circle, but nothing tiggers anymore outside.

Any idea why?

MohG
  • 351
  • 4
  • 11

1 Answers1

0

You can override this method in CircleView:

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
    let center = CGPoint(x: bounds.size.width/2, y: bounds.size.height/2)
    return pow(center.x-point.x, 2) + pow(center.y - point.y, 2) <= pow(bounds.size.width/2, 2)
}

Source

FYI there is also a mistake in your UIViewRepresentable, you need this

func updateUIView(_ uiView: UIView, context: Context) {  
    view.backgroundColor = color
}
malhal
  • 26,330
  • 7
  • 115
  • 133
  • Yep, already tried but doesn't solve the problem. The bottom view does not capture the tap. – MohG Feb 01 '23 at 10:18