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


237

如何将触摸事件添加到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 
  0

为SWIFT你可以从这里得到它:https://stackoverflow.com/questions/28675209/how-to-call-gesture-tap-on -uiview-programmatically-in-swift 07 3月. 182018-03-07 13:45:06

521

在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上有一堆示例代码,可能有所帮助。

  0

但是,这是重写视图的触摸defautlt动作。 ¿是否可以调用视图的默认触摸操作?像[super touchesbegan]之类的东西?... 13 7月. 112011-07-13 15:53:35

+2

CGPoint线做了什么? 13 5月. 122012-05-13 02:11:59

+2

@yourfriendzak“CGPoint”表示点击视图的超级视图中点击的位置。您可以使用此点将轻敲视图(或同级视图)移至轻敲的位置。这在'UIPanGestureRecognizer'的处理程序中用于在屏幕上拖动视图更加有用。 15 5月. 122012-05-15 17:10:02

+5

伟大的简洁的答案,谢谢。但sheesh,如果这件事稍微容易一点,不是很好吗?! :) 20 5月. 122012-05-20 22:56:50

  0

这不是太糟糕,但我希望有一个基于块的API,如https://github.com/neror/ftutils/blob/master/Headers/FTUtils/FTUtils%2BUIGestureRecognizer.h。 Xcode 4也支持在Interface Builder中添加/配置手势识别器。 24 5月. 122012-05-24 16:03:42

  0

我得到了大部分工作;然而,为什么当我打印坐标使用 NSLog(@“接触点:%f,%f”,location.x,location.y); 我总是得到0.00000,0.00000 ???是因为我的模拟器吗?我在我的mac pro上使用我的触控板 08 8月. 122012-08-08 05:20:02

  0

@NathanEror UIView只能添加ONE GestureRecognizer。我尝试处理多个EventHandler。 https://gist.github.com/1450404 07 9月. 122012-09-07 06:38:25

  0

你必须添加view.userInteractionEnabled = YES; 10 3月. 162016-03-10 14:14:14

  0

单击和触摸事件与多个指针和向下/向上/向上状态之间存在差异。几乎每个答案都会谈到单击... 07 8月. 172017-08-07 20:27:43


50

我想你可以简单地使用

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

我的意思是headerView从UIControl延伸。

+6

这是更好的答案。 'UITapGestureRecognizer'不是'UIControlEventTouchDown'的替代品。 “Tap”通常由“UIControlEventTouchDown”和“UIControlEventTouchUpInside”组成。 31 10月. 122012-10-31 02:42:19

+60

'UIView'不是'UIControl',因此无法访问'addTarget:action:forControlEvents:'。 21 11月. 122012-11-21 22:32:40

+8

另请注意,UIControl继承自UIView。为了我的目的,我所要做的只是一个简单的子类型切换。 14 2月. 132013-02-14 04:29:27

+1

您可以将它的类设置为UIControl @RobertJoseph ..转到xib文件并将View Custom类设置为UIControl。现在你可以在其中处理事件。 05 9月. 142014-09-05 11:22:56

+2

那么为什么这是一个更好的解决方案,因为我改变继承来处理水龙头呢? 12 11月. 142014-11-12 19:23:34


16

基础上accepted answer你可以定义一个宏:

#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

如果您在故事板中创建视图,请不要忘记启用“启用用户交互”选项。 25 9月. 132013-09-25 08:23:46

  0

我们应该在.h或.m中定义宏以及参数的名称。我的意思是#define handle_tap(UIView视图,委托委托,SEL选择器)做.. 05 9月. 142014-09-05 11:54:29

  0

sooo方便是sooo的很多方法,谢谢!! A +++ 04 12月. 162016-12-04 10:48:06

  0

更新http://hypple.co 30 5月. 172017-05-30 10:13:52


9

您可以通过在代码中添加手势识别器实现这一目标。

第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从下面

enter image description here

enter image description here

  0

我有多个视图,所以我可以发件人身份证? 06 1月. 162016-01-06 04:11:37

  0

你必须去内部的子视图,然后你可以paas发件人。对于(UIView * view in self.topicScrollView.subviews){//去超级视图 if([view isKindOfClass:[UIButton class]]){//转到那个特定的视图 //在这里你已经达到了这一点。 } } 06 1月. 162016-01-06 09:27:08


5

下面有一个夫特版本:

// 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 
    } 
} 
  0

什么是“BlockTap”? 30 8月. 162016-08-30 13:41:34

+1

哦,男人,忘了那一部分。它是一个自定义功能。这里:https://github.com/goktugyil/EZSwiftExtensions/blob/master/Sources/BlockTap.swift 30 8月. 162016-08-30 15:57:55


79

姿势识别

有许多常用的触摸事件(或姿势),您可以通知您何时将Gesture Recognizer添加到您的视图中。他们下面的手势类型的默认支持:

  • UITapGestureRecognizer点击(触摸屏幕简要一次或多次)
  • UILongPressGestureRecognizer长按(接触时间长了屏幕)
  • UIPanGestureRecognizer(移动你的手指在屏幕上)
  • UISwipeGestureRecognizer刷卡(移动迅速手指)
  • UIPinchGestureRecognizer(移动两个手指在一起或分开 - 通常进行缩放)
  • UIRotationGestureRecognizer旋转

(在圆形方向上移动两个手指)除这些,你也可以制作你自己的自定义手势识别器。

添加手势在界面生成器

拖动从对象库手势识别到你的观点。从文档大纲到您的视图控制器代码手势

enter image description here

调速拖动,以使出口和动作。

enter image description here

添加手势编程

以编程方式添加一个手势,则(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 
    func handleTap(sender: UITapGestureRecognizer) { 
     print("tap") 
    } 
} 

  • sender参数是可选的。如果你不需要对手势的引用,那么你可以将其忽略掉。但是,如果您这样做,请在创建手势时在操作方法名称后面删除(_:)
  • handleTap方法的命名是任意的。使用action: #selector(someMethodName(sender:))命名它。

更多示例

你可以学习,我加入到这些意见,看看他们是如何工作的手势识别。

enter image description here

下面是该项目的代码:

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 
    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 
    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 
    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 
    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 
    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 
    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 
    func handleRotate(gesture: UIRotationGestureRecognizer) { 
     label.text = "Rotate recognized" 

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

注意

  • 您可以将多个手势识别器添加到一个单一视图。但为了简单起见,我没有这样做(除了滑动手势)。如果你需要为你的项目,你应该阅读gesture recognizer documentation。这是相当可以理解和有帮助的。
  • 我上面的示例已知问题:(1)平移视图在下一个手势事件时重置其框架。 (2)第一次滑动时,滑动视图来自错误的方向。 (这些错误在我的例子不应该影响你的手势识别器是如何工作的理解,虽然)

更新了斯威夫特3

+1

你的回答非常好,有帮助的详细描述。这就是为什么我有投票你也回答。但是你只是错过了一条我认为你必须包括在你的答案中的指令,因为你已经详细解释了它。该指令是关于设置“<yourView> .EnableUserInteraction = TRUE”。我希望你同意我的看法。 22 3月. 172017-03-22 05:53:25

  0

@ Er.Vihar:这是一个很好的观点。我会将这个答案添加到我要更新的列表中。在此之前,其他用户可以记下您的评论。 22 3月. 172017-03-22 06:20:08

  0

伟大的文档! 19 1月. 182018-01-19 23:36:33


0

这里是IOS tapgesture; 首先,你需要创建行动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 
{} 

4

斯威夫特3更新

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)) 

0

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

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


4

斯威夫特3:

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

func handleTapGestureRecognizer(_ gestureRecognizer: UITapGestureRecognizer) { 

} 

0

为什么你们不试试SSEventListener

您不需要创建任何手势识别器,并将您的逻辑与另一种方法区分开来。 SSEventListener支持在视图上设置监听器模块以监听单击手势,双击手势和N轻击手势(如果您喜欢),并长按手势。设置一个水龙头手势听众变成这样:

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