ios - UITapGestureRecognizer: ¿funciona en Touchdown, no Touch Up?
tapgesture recognizer swift (4)
Swift (sin subclases)
Aquí hay una versión Swift similar a la respuesta Objective-C de Rob Caraway .
La idea es usar un reconocedor de gestos de pulsación larga con la configuración minimumPressDuration
puesta a cero en lugar de usar un reconocedor de gestos de toque. Esto se debe a que el reconocedor de gestos de pulsación larga informa que los eventos táctiles comienzan mientras que el gesto de tap no.
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var myView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// Add "long" press gesture recognizer
let tap = UILongPressGestureRecognizer(target: self, action: #selector(tapHandler))
tap.minimumPressDuration = 0
myView.addGestureRecognizer(tap)
}
// called by gesture recognizer
@objc func tapHandler(gesture: UITapGestureRecognizer) {
// handle touch down and touch up events separately
if gesture.state == .began {
// do something...
print("tap down")
} else if gesture.state == .ended { // optional for touch up event catching
// do something else...
print("tap up")
}
}
}
Para lo que estoy usando el evento tap es muy sensible al tiempo, entonces tengo curiosidad si es posible hacer que UITapGestureRecognizer se active cuando el usuario simplemente toca hacia abajo, en lugar de requerir que también lo retoque.
Cree su subclase TouchDownGestureRecognizer personalizada e implemente el gesto en touchesBegan:
TouchDownGestureRecognizer.h
#import <UIKit/UIKit.h>
@interface TouchDownGestureRecognizer : UIGestureRecognizer
@end
TouchDownGestureRecognizer.m
#import "TouchDownGestureRecognizer.h"
#import <UIKit/UIGestureRecognizerSubclass.h>
@implementation TouchDownGestureRecognizer
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
if (self.state == UIGestureRecognizerStatePossible) {
self.state = UIGestureRecognizerStateRecognized;
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
self.state = UIGestureRecognizerStateFailed;
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
self.state = UIGestureRecognizerStateFailed;
}
@end
implementación:
#import "TouchDownGestureRecognizer.h"
TouchDownGestureRecognizer *touchDown = [[TouchDownGestureRecognizer alloc] initWithTarget:self action:@selector(handleTouchDown:)];
[yourView addGestureRecognizer:touchDown];
-(void)handleTouchDown:(TouchDownGestureRecognizer *)touchDown{
NSLog(@"Down");
}
Implementación rápida:
import UIKit
import UIKit.UIGestureRecognizerSubclass
class TouchDownGestureRecognizer: UIGestureRecognizer
{
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent)
{
if self.state == .Possible
{
self.state = .Recognized
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent)
{
self.state = .Failed
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent)
{
self.state = .Failed
}
}
Aquí está la sintaxis de Swift para 2017:
import UIKit.UIGestureRecognizerSubclass
class SingleTouchDownGestureRecognizer: UIGestureRecognizer {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
if self.state == .possible {
self.state = .recognized
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
self.state = .failed
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
self.state = .failed
}
}
Tenga en cuenta que este es un reemplazo UITap
para UITap
. Entonces en código como ...
func add(tap v:UIView, _ action:Selector) {
let t = UITapGestureRecognizer(target: self, action: action)
v.addGestureRecognizer(t)
}
puedes cambiar de forma segura a ....
func add(hairtriggerTap v:UIView, _ action:Selector) {
let t = SingleTouchDownGestureRecognizer(target: self, action: action)
v.addGestureRecognizer(t)
}
Las pruebas muestran que no se llamará más de una vez. Funciona como un reemplazo directo; puedes simplemente intercambiar entre las dos llamadas.
Esta es otra solución. Crear la subclase de UIControl. Puedes usarlo como UIView incluso en Storyboard porque UIControl es la subclase de UIView.
class TouchHandlingView: UIControl {
}
Y agregaTarget to it:
@IBOutlet weak var mainView: TouchHandlingView!
...
mainView.addTarget(self, action: "startAction:", forControlEvents: .TouchDown)
...
Entonces la acción designada se llamará como UIButton:
func startAction(sender: AnyObject) {
print("start")
}
Use un UILongPressGestureRecognizer y establezca su minimumPressDuration
en 0. Actuará como un toque hacia abajo durante el estado UIGestureRecognizerStateBegan
.
Para Swift 4
func setupTap() {
let touchDown = UILongPressGestureRecognizer(target:self, action: #selector(didTouchDown))
touchDown.minimumPressDuration = 0
view.addGestureRecognizer(touchDown)
}
func didTouchDown(gesture: UILongPressGestureRecognizer) {
if (gesture.state == .began){
doSomething()
}
}
Para Objective-C
Ejemplo:
-(void)setupLongPress
{
self.longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(didLongPress:)];
self.longPress.minimumPressDuration = 0;
[self.view addGestureRecognizer:self.longPress];
}
-(void)didLongPress:(UILongPressGestureRecognizer *)gesture
{
if (gesture.state == UIGestureRecognizerStateBegan){
[self doSomething];
}
}