如何添加一个触摸事件到一个UIView?

我如何添加一个触摸事件到一个UIView?< br > 我试着:< / p >
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
368697 次浏览

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

我认为你可以简单地使用

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

我的意思是headerView从UIControl扩展过来。

基于接受的答案,你可以定义一个宏:

#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:));

你可以通过在代码中添加手势识别器来实现这一点。

步骤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");
}

注意:这里你的视图在我的案例是@property (strong, nonatomic) IBOutlet UIView *localView;

编辑: *localView是Main中的白框。下面的故事板

enter image description here

enter image description here

以下是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
}
}

手势识别器

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

  • UITapGestureRecognizer 利用(简单地触摸屏幕一次或多次)
  • UILongPressGestureRecognizer 长时间接触(长时间触摸屏幕)
  • UIPanGestureRecognizer (在屏幕上移动你的手指)
  • UISwipeGestureRecognizer 刷卡(快速移动手指)
  • UIPinchGestureRecognizer (移动两个手指一起或分开-通常是缩放)
  • UIRotationGestureRecognizer 旋转(沿圆周方向移动两根手指)

除此之外,你还可以制作自己的手势识别器。

在接口生成器中添加一个手势

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

enter image description here

控件从文档大纲中的手势拖到视图控制器代码中,以创建Outlet和Action。

enter image description here

这应该在默认情况下设置,但也要确保为您的视图将启用用户操作设置为true。

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
@objc func handleTap(sender: UITapGestureRecognizer) {
print("tap")
}
}

笔记

  • sender参数是可选的。如果你不需要一个手势的引用,那么你可以把它去掉。如果你这样做,但是,删除动作方法名称后的(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
@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)第一次滑动时,滑动视图来自错误的方向。(不过,我示例中的这些错误不应该影响您对手势识别器工作方式的理解。)
这是ios的tapgesture手势; 首先,你需要为GestureRecognizer创建动作,在动作下面写下面的代码,如下所示

- (IBAction)tapgesture:(id)sender


{




[_password resignFirstResponder];




[_username resignFirstResponder];


NSLog(@" TapGestureRecognizer  tapped");


}

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

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];

然后,handle click:

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

Swift 3 &斯威夫特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))

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

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

斯威夫特3:

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


func handleTapGestureRecognizer(_ gestureRecognizer: UITapGestureRecognizer) {


}

你们为什么不试试SSEventListener呢?

您不需要创建任何手势识别器,并将您的逻辑分离到另一个方法。SSEventListener支持在视图上设置侦听器块,以侦听单个点击手势,双击手势和N-tap手势,如果你喜欢,和长按手势。设置一个点击手势监听器是这样的:

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

斯威夫特4.2和Xcode 10

使用UITapGestureRecognizer for添加触摸事件

//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...")
}

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

UIView转换为UIControl是这里的正确答案,因为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 < / p >

斯威夫特5.3

使用闭包的解决方案,基于:带有闭包的UIGestureRecognizer

final class BindableGestureRecognizer: UITapGestureRecognizer {
private var action: () -> Void


init(action: @escaping () -> Void) {
self.action = action
super.init(target: nil, action: nil)
self.addTarget(self, action: #selector(execute))
}


@objc private func execute() {
action()
}
}


public extension UIView {
/// A discrete gesture recognizer that interprets single or multiple taps.
/// - Parameters:
///   - tapNumber: The number of taps necessary for gesture recognition.
///   - closure: A selector that identifies the method implemented by the target to handle the gesture recognized by the receiver. The action selector must conform to the signature described in the class overview. NULL is not a valid value.
func addTapGesture(tapNumber: Int = 1, _ closure: (() -> Void)?) {
guard let closure = closure else { return }


let tap = BindableGestureRecognizer(action: closure)
tap.numberOfTapsRequired = tapNumber
addGestureRecognizer(tap)


isUserInteractionEnabled = true
}
}

使用:

view.addTapGesture { [weak self] in
self?.view.backgroundColor = .red
}

简单实用的扩展:

extension UIView {
private struct OnClickHolder {
static var _closure:()->() = {}
}


private var onClickClosure: () -> () {
get { return OnClickHolder._closure }
set { OnClickHolder._closure = newValue }
}


func onTap(closure: @escaping ()->()) {
self.onClickClosure = closure
    

isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(onClickAction))
addGestureRecognizer(tap)
}


@objc private func onClickAction() {
onClickClosure()
}

用法:

    override func viewDidLoad() {
super.viewDidLoad()
let view = UIView(frame: .init(x: 0, y: 0, width: 80, height: 50))
view.backgroundColor  = .red
view.onTap {
print("View Tapped")
}
}