UITapGestureRecognizer点击self.view但忽略子视图

Mat*_*der 80 ios uitapgesturerecognizer

我需要实现一个功能,当我双击self.view(视图UIViewCotroller)时会调用一些代码.但是我在这个视图上有其他UI对象的问题,我不想将任何识别器对象附加到所有这些对象上.我在下面找到了这个方法如何在我的视图上做手势,我知道它是如何工作的.现在我在障碍面前选择哪种方式来创建忽略子视图的识别器.有任何想法吗?谢谢.

UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
[doubleTap setNumberOfTapsRequired:2];
[self.view addGestureRecognizer:doubleTap];
Run Code Online (Sandbox Code Playgroud)

Rav*_*avi 127

您应该UIGestureRecognizerDelegateself对象内部采用协议并调用以下方法来检查视图.在此方法中,检查您的视图touch.view并返回相应的bool(是/否).像这样的东西:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    if ([touch.view isDescendantOfView:yourSubView]) {
        return NO;
    }
    return YES;
}
Run Code Online (Sandbox Code Playgroud)

编辑:拜托,请检查@ Ian的答案!

  • 视图是其自身的后代,因此这不起作用......(不过总体方法还可以,请参阅其他答案) (2认同)

Ian*_*Ian 92

另一种方法是仅比较触摸视图是否为手势视图,因为后代不会通过该条件.一个漂亮,简单的单行:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    return touch.view == gestureRecognizer.view
}
Run Code Online (Sandbox Code Playgroud)

  • 这对我来说比接受的答案更好.更简洁. (2认同)

Ant*_*ine 20

而对于Swift变种:

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
    if touch.view.isDescendantOfView(yourSubView){
        return false
    }
    return true
}
Run Code Online (Sandbox Code Playgroud)

很高兴知道,isDescendantOfView返回一个Boolean值,指示接收者是给定视图的子视图还是与该视图相同.

  • 而不是那样做if语句,你不能只返回这个吗?return!touch.view.isDescendant(of:gestureRecognizer.view)另外,swift 3 ^^中的新语法 (4认同)

Arr*_*rru 8

完整的快速解决方案(必须实现委托并为识别器设置):

class MyViewController: UIViewController UIGestureRecognizerDelegate {

    override func viewDidLoad() {
        let doubleTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(onBaseTapOnly))
        doubleTapRecognizer.numberOfTapsRequired = 2
        doubleTapRecognizer.delegate = self
        self.view.addGestureRecognizer(doubleTapRecognizer)
    }

    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
        if touch.view.isDescendantOfView(self.view){
            return false
        }
        return true
    }

    func onBaseTapOnly(sender: UITapGestureRecognizer) {
        if sender.state == .Ended {
            //react to tap
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Coa*_*hys 6

使用您触摸的 CGPoint 的变体 (SWIFT 4.0)

class MyViewController: UIViewController, UIGestureRecognizerDelegate {

  func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {

// Get the location in CGPoint
    let location = touch.location(in: nil)

// Check if location is inside the view to avoid
    if viewToAvoid.frame.contains(location) {
        return false
    }

    return true
  }
}
Run Code Online (Sandbox Code Playgroud)


Ima*_*tit 5

在Swift 5和iOS 12中,UIGestureRecognizerDelegate有一个名为的方法gestureRecognizer(_:shouldReceive:)gestureRecognizer(_:shouldReceive:)具有以下声明:

询问代表手势识别器是否应该接收代表触摸的对象。

optional func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool
Run Code Online (Sandbox Code Playgroud)

以下完整的代码显示了的可能实现gestureRecognizer(_:shouldReceive:)。使用此代码,点击ViewController的视图(包括imageView)的子视图将不会触发该printHello(_:)方法。

import UIKit

class ViewController: UIViewController, UIGestureRecognizerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(printHello))
        tapGestureRecognizer.delegate = self
        view.addGestureRecognizer(tapGestureRecognizer)

        let imageView = UIImageView(image: UIImage(named: "icon")!)
        imageView.frame = CGRect(x: 50, y: 50, width: 100, height: 100)
        view.addSubview(imageView)

        // ?? Enable user interaction for imageView so that it can participate to touch events.
        // Otherwise, taps on imageView will be forwarded to its superview and managed by it.
        imageView.isUserInteractionEnabled = true
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        // Prevent subviews of a specific view to send touch events to the view's gesture recognizers.
        if let touchedView = touch.view, let gestureView = gestureRecognizer.view, touchedView.isDescendant(of: gestureView), touchedView !== gestureView {
            return false
        }
        return true
    }

    @objc func printHello(_ sender: UITapGestureRecognizer) {
        print("Hello")
    }

}
Run Code Online (Sandbox Code Playgroud)

的替代实现gestureRecognizer(_:shouldReceive:)可以是:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    return gestureRecognizer.view === touch.view
}
Run Code Online (Sandbox Code Playgroud)

但是请注意,此替代代码不会检查是否touch.view是的子视图gestureRecognizer.view


Mus*_*tri 5

清除 Swift 方式

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    return touch.view == self.view
}
Run Code Online (Sandbox Code Playgroud)