如何将触摸事件添加到UIView?


280

如何将触摸事件添加到UIView?
我尝试:

UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, nextY)] autorelease];
[headerView addTarget:self action:@selector(myEvent:) forControlEvents:UIControlEventTouchDown];
// ERROR MESSAGE: UIView may not respond to '-addTarget:action:forControlEvents:'

我不想创建一个子类并覆盖

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

:对于SWIFT你可以从这里得到它stackoverflow.com/questions/28675209/...
Mr.Javed Multani

Answers:


578

在iOS 3.2及更高版本中,您可以使用手势识别器。例如,这是处理轻敲事件的方式:

//The setup code (in viewDidLoad in your view controller)
UITapGestureRecognizer *singleFingerTap = 
  [[UITapGestureRecognizer alloc] initWithTarget:self 
                                          action:@selector(handleSingleTap:)];
[self.view addGestureRecognizer:singleFingerTap];

//The event handling method
- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
  CGPoint location = [recognizer locationInView:[recognizer.view superview]];

  //Do stuff here...
}

也有很多内置手势。查看有关iOS事件处理和的文档UIGestureRecognizer。我也有一堆的示例代码了github上可能会有帮助。


但这就是覆盖视图的触摸解除动作。¿可以调用视图的默认触摸动作吗?像[super touchesBegan]吗?...
M Penades 2011年

2
CGPoint系列有什么作用?
zakdances 2012年

2
@yourfriendzak CGPoint表示点击的视图的超级视图中水龙头的位置。您可以使用此点将点击视图(或同级视图)移动到点击位置。这在处理程序中对于UIPanGestureRecognizer在屏幕上拖动视图更为有用。
内森·埃罗

5
非常简洁的答案,谢谢。但是,如果这样容易一点会不会很好?:)
natbro 2012年

还算不错,但是我希望有一个基于块的API,例如github.com/neror/ftutils/blob/master/Headers/FTUtils/…。Xcode 4确实也支持在Interface Builder中添加/配置手势识别器。
内森·埃罗

126

手势识别器

手势识别器添加到视图时,可以通知许多常用的触摸事件(或手势)。默认情况下支持以下手势类型:

  • UITapGestureRecognizer 点按(短暂触摸屏幕一次或多次)
  • UILongPressGestureRecognizer 长按长时间触摸屏幕)
  • UIPanGestureRecognizer 平移(在屏幕上移动手指)
  • UISwipeGestureRecognizer 滑动(快速移动手指)
  • UIPinchGestureRecognizer (将两个手指并拢或分开移动-通常进行缩放)
  • UIRotationGestureRecognizer 旋转(沿圆周方向移动两个手指)

除了这些,您还可以制作自己的自定义手势识别器。

在界面生成器中添加手势

将手势识别器从对象库拖到视图上。

在此处输入图片说明

控制从Document Outline中的手势拖到View Controller代码中,以创建一个Outlet和一个Action。

在此处输入图片说明

默认情况下应设置此选项,但还应确保您的视图的“启用用户操作”设置为true。

在此处输入图片说明

以编程方式添加手势

要以编程方式添加手势,您(1)创建一个手势识别器,(2)将其添加到视图中,以及(3)制作一个在识别手势时调用的方法。

import UIKit
class ViewController: UIViewController {

    @IBOutlet weak var myView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // 1. create a gesture recognizer (tap gesture)
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:)))

        // 2. add the gesture recognizer to a view
        myView.addGestureRecognizer(tapGesture)
    }

    // 3. this method is called when a tap is recognized
    @objc func handleTap(sender: UITapGestureRecognizer) {
        print("tap")
    }
}

笔记

  • sender参数是可选的。如果不需要引用手势,则可以将其省略。但是,如果这样做,请删除(sender:)操作方法名称之后的。
  • handleTap方法的命名是任意的。命名为任何您想使用的。action: #selector(someMethodName(sender:))

更多例子

您可以研究我添加到这些视图中的手势识别器,以了解它们的工作原理。

在此处输入图片说明

这是该项目的代码:

import UIKit
class ViewController: UIViewController {

    @IBOutlet weak var tapView: UIView!
    @IBOutlet weak var doubleTapView: UIView!
    @IBOutlet weak var longPressView: UIView!
    @IBOutlet weak var panView: UIView!
    @IBOutlet weak var swipeView: UIView!
    @IBOutlet weak var pinchView: UIView!
    @IBOutlet weak var rotateView: UIView!
    @IBOutlet weak var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Tap
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap))
        tapView.addGestureRecognizer(tapGesture)

        // Double Tap
        let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap))
        doubleTapGesture.numberOfTapsRequired = 2
        doubleTapView.addGestureRecognizer(doubleTapGesture)

        // Long Press
        let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(gesture:)))
        longPressView.addGestureRecognizer(longPressGesture)

        // Pan
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(gesture:)))
        panView.addGestureRecognizer(panGesture)

        // Swipe (right and left)
        let swipeRightGesture = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipe(gesture:)))
        let swipeLeftGesture = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipe(gesture:)))
        swipeRightGesture.direction = UISwipeGestureRecognizerDirection.right
        swipeLeftGesture.direction = UISwipeGestureRecognizerDirection.left
        swipeView.addGestureRecognizer(swipeRightGesture)
        swipeView.addGestureRecognizer(swipeLeftGesture)

        // Pinch
        let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch(gesture:)))
        pinchView.addGestureRecognizer(pinchGesture)

        // Rotate
        let rotateGesture = UIRotationGestureRecognizer(target: self, action: #selector(handleRotate(gesture:)))
        rotateView.addGestureRecognizer(rotateGesture)

    }

    // Tap action
    @objc func handleTap() {
        label.text = "Tap recognized"

        // example task: change background color
        if tapView.backgroundColor == UIColor.blue {
            tapView.backgroundColor = UIColor.red
        } else {
            tapView.backgroundColor = UIColor.blue
        }

    }

    // Double tap action
    @objc func handleDoubleTap() {
        label.text = "Double tap recognized"

        // example task: change background color
        if doubleTapView.backgroundColor == UIColor.yellow {
            doubleTapView.backgroundColor = UIColor.green
        } else {
            doubleTapView.backgroundColor = UIColor.yellow
        }
    }

    // Long press action
    @objc func handleLongPress(gesture: UILongPressGestureRecognizer) {
        label.text = "Long press recognized"

        // example task: show an alert
        if gesture.state == UIGestureRecognizerState.began {
            let alert = UIAlertController(title: "Long Press", message: "Can I help you?", preferredStyle: UIAlertControllerStyle.alert)
            alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
            self.present(alert, animated: true, completion: nil)
        }
    }

    // Pan action
    @objc func handlePan(gesture: UIPanGestureRecognizer) {
        label.text = "Pan recognized"

        // example task: drag view
        let location = gesture.location(in: view) // root view
        panView.center = location
    }

    // Swipe action
    @objc func handleSwipe(gesture: UISwipeGestureRecognizer) {
        label.text = "Swipe recognized"

        // example task: animate view off screen
        let originalLocation = swipeView.center
        if gesture.direction == UISwipeGestureRecognizerDirection.right {
            UIView.animate(withDuration: 0.5, animations: {
                self.swipeView.center.x += self.view.bounds.width
            }, completion: { (value: Bool) in
                self.swipeView.center = originalLocation
            })
        } else if gesture.direction == UISwipeGestureRecognizerDirection.left {
            UIView.animate(withDuration: 0.5, animations: {
                self.swipeView.center.x -= self.view.bounds.width
            }, completion: { (value: Bool) in
                self.swipeView.center = originalLocation
            })
        }
    }

    // Pinch action
    @objc func handlePinch(gesture: UIPinchGestureRecognizer) {
        label.text = "Pinch recognized"

        if gesture.state == UIGestureRecognizerState.changed {
            let transform = CGAffineTransform(scaleX: gesture.scale, y: gesture.scale)
            pinchView.transform = transform
        }
    }

    // Rotate action
    @objc func handleRotate(gesture: UIRotationGestureRecognizer) {
        label.text = "Rotate recognized"

        if gesture.state == UIGestureRecognizerState.changed {
            let transform = CGAffineTransform(rotationAngle: gesture.rotation)
            rotateView.transform = transform
        }
    }
}

笔记

  • 您可以将多个手势识别器添加到单个视图。但是,为了简单起见,我没有这样做(除了滑动手势)。如果需要用于项目,则应阅读手势识别器文档。这是相当容易理解和有用的。
  • 我上面的示例的已知问题:(1)全景视图在下一个手势事件时重置其框架。(2)滑动视图在第一次滑动时方向错误。(不过,我示例中的这些错误不应影响您对手势识别器工作原理的理解。)

2
您的答案非常好,并且有详细的说明会有所帮助。那就是为什么我要投赞成票,你也要回答。但是您只是错过了一条说明,我认为您必须在回答中包含详细说明的内容。该指令是关于设置“ <yourView> .EnableUserInteraction = TRUE”的。我希望你同意我的看法。
Er Vihar

3
为了使这项工作可行,UIView您还需要添加:self.isUserInteractionEnabled = true;
neiker

52

我想你可以简单地使用

UIControl *headerView = ...
[headerView addTarget:self action:@selector(myEvent:) forControlEvents:UIControlEventTouchDown];

我的意思是headerView从UIControl扩展。


7
这是更好的答案。UITapGestureRecognizer不能代替UIControlEventTouchDown。甲Tap通常组成的UIControlEventTouchDownUIControlEventTouchUpInside
哦,2012年

62
A UIView不是a UIControl,因此无法访问addTarget:action:forControlEvents:
罗伯特·约瑟夫(RobertJoseph)2012年

9
另请注意,UIControl继承自UIView。出于我的目的,我要做的只是一个简单的子类类型开关。
pretzels1337

1
您可以将其类设置为UIControl @RobertJoseph ..转到xib文件并将“视图自定义”类设置为UIControl。现在你可以在它处理事件..
扎尔ËAhmer

2
那么,既然我要更改继承来处理水龙头,又为什么又是一个更好的解决方案呢?
Anthony Glyadchenko 2014年

21

Swift 3和Swift 4

import UIKit

extension UIView {
  func addTapGesture(tapNumber: Int, target: Any, action: Selector) {
    let tap = UITapGestureRecognizer(target: target, action: action)
    tap.numberOfTapsRequired = tapNumber
    addGestureRecognizer(tap)
    isUserInteractionEnabled = true
  }
}

采用

yourView.addTapGesture(tapNumber: 1, target: self, action: #selector(yourMethod))

谢谢。很棒!
Mikrasya

1
喜欢这个!添加到所有项目中;)
budidino

17

根据接受的答案,您可以定义一个宏:

#define handle_tap(view, delegate, selector) do {\
    view.userInteractionEnabled = YES;\
    [view addGestureRecognizer: [[UITapGestureRecognizer alloc] initWithTarget:delegate action:selector]];\
} while(0)

该宏使用ARC,因此没有release调用。

宏用法示例:

handle_tap(userpic, self, @selector(onTapUserpic:));

4
如果您在情节提要中创建视图,请不要忘记启用“启用用户交互”选项。
大卫

我们应该在.h或.m中定义宏,参数的名称应该是什么。我的意思是#define handle_tap(UIView view,Delegate委托,SEL选择器)做..
Zar E Ahmer 2014年

8

您可以通过在代码中添加Gesture Recogniser来实现。

步骤1: ViewController.m:

// Declare the Gesture.
UITapGestureRecognizer *gesRecognizer = [[UITapGestureRecognizer alloc] 
                                          initWithTarget:self 
                                          action:@selector(handleTap:)];
gesRecognizer.delegate = self;

// Add Gesture to your view.
[yourView addGestureRecognizer:gesRecognizer]; 

步骤2: ViewController.m:

// Declare the Gesture Recogniser handler method.
- (void)handleTap:(UITapGestureRecognizer *)gestureRecognizer{
   NSLog(@"Tapped");
}

注意:在我的情况下,此处的yourView是 @property (strong, nonatomic) IBOutlet UIView *localView;

编辑: * localView是从下面Main.storyboard中的白框

在此处输入图片说明

在此处输入图片说明


我有多个视图,所以发送人ID可以吗?
Moin Shirazi

您必须转到内部子视图,然后才能暂停发送方。---------对于(UIView * self.topicScrollView.subviews中的view){//进入超级视图,如果([view isKindOfClass: [UIButton类]] {//转到该特定视图//至此为止。}
Annu

8

Swift 4.2和Xcode 10中

使用UITapGestureRecognizer添加触摸事件

//Add tap gesture to your view
let tap = UITapGestureRecognizer(target: self, action: #selector(handleGesture))
yourView.addGestureRecognizer(tap)

// GestureRecognizer
@objc func handleGesture(gesture: UITapGestureRecognizer) -> Void {
//Write your code here
}

如果要使用SharedClass

//This is my shared class
import UIKit

class SharedClass: NSObject {

    static let sharedInstance = SharedClass()

    //Tap gesture function
    func addTapGesture(view: UIView, target: Any, action: Selector) {
        let tap = UITapGestureRecognizer(target: target, action: action)
        view.addGestureRecognizer(tap)
    }
} 

我的ViewController中有3个视图,分别称为view1,view2和view3。

override func viewDidLoad() {
    super.viewDidLoad()
    //Add gestures to your views
    SharedClass.sharedInstance.addTapGesture(view: view1, target: self, action: #selector(handleGesture))
    SharedClass.sharedInstance.addTapGesture(view: view2, target: self, action: #selector(handleGesture))
    SharedClass.sharedInstance.addTapGesture(view: view3, target: self, action: #selector(handleGesture2))

}

// GestureRecognizer
@objc func handleGesture(gesture: UITapGestureRecognizer) -> Void {
    print("printed 1&2...")
}
// GestureRecognizer
@objc func handleGesture2(gesture: UITapGestureRecognizer) -> Void {
    print("printed3...")
}

6

这是Swift版本:

// MARK: Gesture Extensions
extension UIView {

    func addTapGesture(#tapNumber: Int, target: AnyObject, action: Selector) {
        let tap = UITapGestureRecognizer (target: target, action: action)
        tap.numberOfTapsRequired = tapNumber
        addGestureRecognizer(tap)
        userInteractionEnabled = true
    }

    func addTapGesture(#tapNumber: Int, action: ((UITapGestureRecognizer)->())?) {
        let tap = BlockTap (tapCount: tapNumber, fingerCount: 1, action: action)
        addGestureRecognizer(tap)
        userInteractionEnabled = true
    }
}

是什么BlockTap
何一非何一非2016年

1
哦,老兄,忘记了那部分。它是一个自定义功能。此处:github.com/goktugyil/EZSwiftExtensions/blob/master/Sources/…– Esqarrouth
2016年

5

斯威夫特3:

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

func handleTapGestureRecognizer(_ gestureRecognizer: UITapGestureRecognizer) {

}

1

这些天似乎很简单。这是Swift版本。

let tap = UITapGestureRecognizer(target: self, action: #selector(viewTapped))
    view.addGestureRecognizer(tap)

@objc func viewTapped(recognizer: UIGestureRecognizer)
{
    //Do what you need to do!
}

0

这是iOS手势;首先,您需要在该动作下编写以下代码后,为GestureRecognizer创建动作,如下所示

- (IBAction)tapgesture:(id)sender

{


[_password resignFirstResponder];


[_username resignFirstResponder];

NSLog(@" TapGestureRecognizer  tapped");

}

0

另一种方法是向视图添加透明按钮

UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom];
b.frame = CGRectMake(0, 0, headerView.width, headerView.height);
[headerView addSubview:b];
[b addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchDown];

然后,处理单击:

- (void)buttonClicked:(id)sender
{}

0

创建一个手势识别器(子类),它将实现触摸事件,例如 touchesBegan。之后,您可以将其添加到视图中。

这样,您将使用组合而不是子类化(这是请求)。


0

你们为什么不尝试SSEventListener呢?

您无需创建任何手势识别器并将逻辑与其他方法分开。SSEventListener支持在视图上设置侦听器块,以侦听单击手势,双击手势和N-tap手势(如果您愿意)以及长按手势。设置单个点击手势侦听器的方式如下:

[view ss_addTapViewEventListener:^(UITapGestureRecognizer *recognizer) { ... } numberOfTapsRequired:1];


0

目标C:

UIControl *headerView = [[UIControl alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, nextY)];
[headerView addTarget:self action:@selector(myEvent:) forControlEvents:UIControlEventTouchDown];

迅速:

let headerView = UIControl(frame: CGRect(x: 0, y: 0, width: tableView.bounds.size.width, height: nextY))
headerView.addTarget(self, action: #selector(myEvent(_:)), for: .touchDown)

问题问:

如何将触摸事件添加到UIView?

它不要求点击事件。

特别是OP想要实施 UIControlEventTouchDown

切换UIViewUIControl这里是正确的答案,因为Gesture Recognisers不知道什么.touchDown.touchUpInside.touchUpOutside等。

此外,UIControl继承自UIView,因此您不会丢失任何功能。

如果只需要轻按一下,则可以使用手势识别器。但是,如果您想要更好的控制(如该问题所要求的),则需要UIControl。

https://developer.apple.com/documentation/uikit/uicontrol?language=objc https://developer.apple.com/documentation/uikit/uigesturerecognizer?language=objc

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.