在重叠区域点击手势事件

Tap gesture events on overlapping area

我有一个带有黑色边框的视图,它有两个不同的视图。而且这些观点在一个小范围内是重叠的。他们每个人都有自己的 UITapGestureRecognizer。当我点击每个项目的离散区域时,会触发该项目的操作。但是当我点击公共区域时,只会触发第二个视图的操作。我希望必须触发这两个动作。我怎样才能做到这一点?这是我的代码:

class ViewController: UIViewController {

  @IBOutlet weak var view1: UIView!
  @IBOutlet weak var view2: UIView!
  @IBOutlet weak var outerView: UIView!

  override func viewDidLoad() {
      super.viewDidLoad()
      outerView.layer.borderWidth = 2.0
      outerView.layer.borderColor = UIColor.black.cgColor
      view1.layer.borderWidth = 2.0
      view1.layer.borderColor = UIColor.red.cgColor
      view2.layer.borderWidth = 2.0
      view2.layer.borderColor = UIColor.blue.cgColor
      self.initialize()
  }

  private func initialize(){
      let tapGesture1 = UITapGestureRecognizer(target: self, action: #selector(detectTap1(_:)))
      let tapGesture2 = UITapGestureRecognizer(target: self, action: #selector(detectTap2(_:)))
      self.view1.addGestureRecognizer(tapGesture1)
      self.view2.addGestureRecognizer(tapGesture2)
  }

  @objc func detectTap1(_ gesture : UITapGestureRecognizer) {
      print("detectTap1")
  }

  @objc func detectTap2(_ gesture : UITapGestureRecognizer) {
      print("detectTap2")
  }
}

请分享您的建议。

尝试以下操作:

private func initialize(){

        let tapGesture1 = UITapGestureRecognizer(target: self, action: #selector(detectTap1(_:)))
        let tapGesture2 = UITapGestureRecognizer(target: self, action: #selector(detectTap2(_:)))
        tapGesture1.cancelsTouchesInView = false
        tapGesture2.cancelsTouchesInView = false
        self.view1.addGestureRecognizer(tapGesture1)
        self.view2.addGestureRecognizer(tapGesture2)
 }

当您设置

gesture.cancelsTouchesInView = false

它将手势传播到下面的视图。

尝试实现此 UIGestureRecognizerDelegate 方法:

class ViewController: UIViewController, UIGestureRecognizerDelegate {

... 
...

private func initialize() {
...
  gesture1.delegate = self
  gesture2.delegate = self
...
}

func gestureRecognizer(
_ gestureRecognizer: UIGestureRecognizer,
 shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer
) -> Bool {
    // its up to you 
    //guard otherGestureRecognizer == yourAnotherGesture else { return false }
    return true
}

对于这个问题,我找到了这个解决方案,也许不是最好的解决方案,但它有效,无论如何我会寻求进一步的改进

我有 subclassed UIGestureRecognizer class

已更新

import UIKit
import UIKit.UIGestureRecognizerSubclass

class CustomGestureRecognizer: UIGestureRecognizer {

    var anotherGestureRecognizer : CustomGestureRecognizer?
    private var touchBeganSended : Bool = false
    private var touchLocation : CGPoint?

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
        super.touchesBegan(touches, with: event)
        if let validTouch = touches.first?.location(in: self.view) {
            if (self.view!.point(inside: validTouch, with: event)) {
                if(!touchBeganSended) {
                    touchBeganSended = true
                    touchLocation = validTouch
                    anotherGestureRecognizer?.touchesBegan(touches, with: event)
                    state = .recognized
                }
            }
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
        super.touchesEnded(touches, with: event)
        if let validTouch = touches.first?.location(in: self.view) {
            if (self.view!.point(inside: validTouch, with: event)) {
                if(touchBeganSended) {
                    touchBeganSended = false
                    anotherGestureRecognizer?.touchesEnded(touches, with: event)
                    state = .recognized
                }
            }
        }
    }

    override func location(in view: UIView?) -> CGPoint {
        if let desiredView = view {
            if(desiredView == self.view) {
                return touchLocation ?? CGPoint(x: 0, y: 0)
            } else {
                return super.location(in: view)
            }
        } else {
            return super.location(in: view)
        }
    }
}

已更新

那么你需要将你的 initialize() 方法修改为这个,最后一个 update 你不需要考虑哪个视图位于视图层次结构的顶部

private func initialize(){
    let tapGesture1 = CustomGestureRecognizer(target: self, action: #selector(detectTap1(_:)))
    let tapGesture2 = CustomGestureRecognizer(target: self, action: #selector(detectTap2(_:)))
    tapGesture1.cancelsTouchesInView = true
    tapGesture1.delegate = self
    tapGesture2.cancelsTouchesInView = true
    tapGesture2.delegate = self
    self.view1.addGestureRecognizer(tapGesture1)
    tapGesture1.anotherGestureRecognizer = tapGesture2
    tapGesture2.anotherGestureRecognizer = tapGesture1
    self.view2.addGestureRecognizer(tapGesture2)
}

正如您在此处看到的那样有效