¿Cómo agregar un evento táctil a un UIView?

¿Cómo agrego un evento táctil a un UIView?
Lo bash:

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:' 

No quiero crear una subclase y sobrescribir

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

En iOS 3.2 y superior, puedes usar reconocedores de gestos. Por ejemplo, así es como manejarías un evento tap:

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

Hay un montón de gestos incorporados también. Consulte los documentos para el manejo de eventos de iOS y UIGestureRecognizer . También tengo un montón de código de muestra en github que podría ayudar.

Reconocedores de gestos

Hay una serie de eventos táctiles comúnmente utilizados (o gestos) de los que puede recibir notificaciones cuando agrega un Reconocedor de gestos a su vista. Los siguientes tipos de gestos son compatibles por defecto:

  • UITapGestureRecognizer Toque (tocando la pantalla brevemente una o más veces)
  • UILongPressGestureRecognizer Long touch (tocando la pantalla durante mucho tiempo)
  • UIPanGestureRecognizer Pan (moviendo el dedo por la pantalla)
  • UISwipeGestureRecognizer Swipe (moviendo el dedo rápidamente)
  • Pellizco UIPinchGestureRecognizer (moviendo dos dedos juntos o separados, generalmente para acercar)
  • UIRotationGestureRecognizer Rotate (moviendo dos dedos en una dirección circular)

Además de estos, también puede hacer su propio reconocedor de gestos personalizado.

Agregar un gesto en el generador de interfaz

Arrastre un reconocedor de gestos de la biblioteca de objetos a su vista.

enter image description here

Controle el arrastre del gesto en el contorno del documento al código de su controlador de vista para hacer un Outlet y una acción.

enter image description here

Esto debe establecerse de manera predeterminada, pero también asegúrese de que la Acción del usuario habilitada esté configurada como verdadera para su vista.

enter image description here

Agregar un gesto programáticamente

Para agregar un gesto mediante progtwigción, (1) crea un reconocedor de gestos, (2) lo agrega a una vista y (3) crea un método que se llama cuando se reconoce el gesto.

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

Notas

  • El parámetro del sender es opcional. Si no necesita una referencia al gesto, puede dejarlo fuera. Sin embargo, si lo hace, elimine el (sender:) después del nombre del método de acción.
  • La denominación del método handleTap fue arbitraria. Llámalo como quieras con la action: #selector( someMethodName (sender:)) .

Más ejemplos

Puede estudiar los reconocedores de gestos que agregué a estas vistas para ver cómo funcionan.

enter image description here

Aquí está el código para ese proyecto:

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

Notas

  • Puede agregar múltiples reconocedores de gestos a una sola vista. En aras de la simplicidad, sin embargo, no hice eso (excepto por el gesto de deslizar). Si necesita para su proyecto, debe leer la documentación del reconocedor de gestos . Es bastante comprensible y útil.
  • Problemas conocidos con mis ejemplos anteriores: (1) Panview restablece su marco en el siguiente evento de gesto. (2) La vista de deslizamiento viene de la dirección incorrecta en el primer deslizamiento. (Estos errores en mis ejemplos no deberían afectar tu comprensión de cómo funcionan los reconocedores de gestos).

Creo que puedes simplemente usar

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

Quiero decir que headerView se extiende desde UIControl.

En función de la respuesta aceptada , puede definir una macro:

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

Esta macro usa ARC, por lo que no hay llamada de release .

Ejemplo de uso de macro:

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

Swift 3 y 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 } } 

Utilizar

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

Puede lograr esto agregando Gesture Recogniser en su código.

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

Paso 2: ViewController.m:

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

NOTA: aquí suView en mi caso fue @property (strong, nonatomic) IBOutlet UIView *localView;

EDIT: * localView es el cuadro blanco en Main.storyboard desde abajo

enter image description here

enter image description here

Heres una versión 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 } } 

Swift 3:

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

Aquí está ios tapgesture; Primero debe crear una acción para GestureRecognizer después de escribir el siguiente código debajo de la acción como se muestra a continuación

 - (IBAction)tapgesture:(id)sender { [_password resignFirstResponder]; [_username resignFirstResponder]; NSLog(@" TapGestureRecognizer tapped"); } 

Otra forma es agregar un botón transparente a la vista

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

Y luego, manejar el clic:

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

Cree un reconocedor de gestos (subclase), que implementará eventos táctiles, como touchesBegan . Puede agregarlo a la vista después de eso.

De esta forma, usarás composición en lugar de subclases (que fue la solicitud).

¿Por qué ustedes no prueban SSEventListener ?

No necesita crear ningún reconocedor de gestos y separar su lógica en otro método. SSEventListener admite la configuración de bloques de escucha en una vista para escuchar un solo toque, un doble toque y un gesto de N-tap si lo desea, y mantenga presionado el gesto. Configurar un solo escucha de gesto de toque se convierte de esta manera:

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