UITapGestureRecognizer - make it work when touched, not touched?

What I use for the tap event is very time sensitive, so I'm curious if it's possible to activate the UITapGestureRecognizer when the user just touches, instead of requiring them to fit too?

+76
ios objective-c swift uitapgesturerecognizer
Mar 26 '13 at 2:10
source share
4 answers

Create your own subclass of TouchDownGestureRecognizer and apply the gesture in touchsBegan:

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 

implementation:

 #import "TouchDownGestureRecognizer.h" TouchDownGestureRecognizer *touchDown = [[TouchDownGestureRecognizer alloc] initWithTarget:self action:@selector(handleTouchDown:)]; [yourView addGestureRecognizer:touchDown]; -(void)handleTouchDown:(TouchDownGestureRecognizer *)touchDown{ NSLog(@"Down"); } 



Quick implementation:

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



Here is the Swift syntax for 2017 to insert:

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

Please note that this is a replacement for UITap . So, in code like ...

 func add(tap v:UIView, _ action:Selector) { let t = UITapGestureRecognizer(target: self, action: action) v.addGestureRecognizer(t) } 

you can safely swap ....

 func add(hairtriggerTap v:UIView, _ action:Selector) { let t = SingleTouchDownGestureRecognizer(target: self, action: action) v.addGestureRecognizer(t) } 

Testing shows that it will not be called more than once. It works as a replacement; You can simply switch between two calls.

+124
Mar 26 '13 at 4:09
source share

Use the UILongPressGestureRecognizer and set its minimumPressDuration to 0. It will act as a touch during the state of the UIGestureRecognizerStateBegan .

For Swift 4

 func setupTap() { let touchDown = UILongPressGestureRecognizer(target:self, action: #selector(didTouchDown)) touchDown.minimumPressDuration = 0 view.addGestureRecognizer(touchDown) } @objc func didTouchDown(gesture: UILongPressGestureRecognizer) { if gesture.state == .began { doSomething() } } 

For Objective-C

Example:

 -(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]; } } 
+156
Aug 05 '13 at 15:23
source share

Swift (no subclass)

Here is a Swift version similar to Rob Caraway Objective-C .

The idea is to use a long click gesture recognizer with minimumPressDuration set to zero, rather than using a click gesture recognizer. This is due to the fact that the long-awaited gesture recognizer reports touch events, while there is no gesture.

 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") } } } 
+19
Jul 01 '16 at 10:55
source share

This is another solution. Subclass UIControl. You can use it as a UIView even on a Storyboard, because UIControl is a subclass of UIView.

 class TouchHandlingView: UIControl { } 

And addTarget to it:

 @IBOutlet weak var mainView: TouchHandlingView! ... mainView.addTarget(self, action: "startAction:", forControlEvents: .TouchDown) ... 

Then the specified action will be called as UIButton:

 func startAction(sender: AnyObject) { print("start") } 
0
Feb 21 '16 at 11:00
source share



All Articles