Ce que j'utilise pour l'événement tap est très sensible au facteur temps, donc je suis curieux de savoir s'il est possible d'activer UITapGestureRecognizer lorsque l'utilisateur touche simplement au sol, au lieu de leur demander également de faire une retouche?
Créez votre sous-classe personnalisée TouchDownGestureRecognizer et implémentez le geste dans 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
la mise en oeuvre:
#import "TouchDownGestureRecognizer.h"
TouchDownGestureRecognizer *touchDown = [[TouchDownGestureRecognizer alloc] initWithTarget:self action:@selector(handleTouchDown:)];
[yourView addGestureRecognizer:touchDown];
-(void)handleTouchDown:(TouchDownGestureRecognizer *)touchDown{
NSLog(@"Down");
}
Mise en œuvre rapide:
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
}
}
Voici la syntaxe Swift pour 2017 à coller:
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
}
}
Notez qu'il s'agit d'un remplacement instantané de UITap
. Donc, dans le code comme ...
func add(tap v:UIView, _ action:Selector) {
let t = UITapGestureRecognizer(target: self, action: action)
v.addGestureRecognizer(t)
}
vous pouvez échanger en toute sécurité pour ....
func add(hairtriggerTap v:UIView, _ action:Selector) {
let t = SingleTouchDownGestureRecognizer(target: self, action: action)
v.addGestureRecognizer(t)
}
Les tests montrent qu'il ne sera pas appelé plus d'une fois. Cela fonctionne comme un remplacement immédiat; vous pouvez simplement permuter entre les deux appels.
Utilisez un UILongPressGestureRecognizer et définissez son minimumPressDuration
sur 0. Il agira comme un toucher du sol pendant l’état UIGestureRecognizerStateBegan
.
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()
}
}
Exemple:
-(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];
}
}
Voici une Swift similaire à réponse Objective-C de Rob Caraway .
L'idée est d'utiliser un identificateur de geste de pression longue avec le minimumPressDuration
défini sur zéro plutôt que d'utiliser un identificateur de geste de tapotement. Cela est dû au fait que les rapports de reconnaissance des gestes de presse longs signalent que les contacts ont commencé des événements, contrairement au geste de toucher.
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")
}
}
}
C'est une autre solution. Créer une sous-classe de UIControl. Vous pouvez l'utiliser comme UIView même dans Storyboard, car UIControl est une sous-classe d'UIView.
class TouchHandlingView: UIControl {
}
Et ajoutez-y la cible:
@IBOutlet weak var mainView: TouchHandlingView!
...
mainView.addTarget(self, action: "startAction:", forControlEvents: .TouchDown)
...
Ensuite, l'action désignée s'appellera comme UIButton:
func startAction(sender: AnyObject) {
print("start")
}