Quello per cui sto usando l'evento tap è molto sensibile al tempo, quindi sono curioso di sapere se è possibile attivare UITapGestureRecognizer quando l'utente tocca semplicemente terra, piuttosto che richiedere anche loro di ritoccare?
Quello per cui sto usando l'evento tap è molto sensibile al tempo, quindi sono curioso di sapere se è possibile attivare UITapGestureRecognizer quando l'utente tocca semplicemente terra, piuttosto che richiedere anche loro di ritoccare?
Risposte:
Crea la tua sottoclasse TouchDownGestureRecognizer personalizzata e implementa i gesti nei tocchi
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
implementazione:
#import "TouchDownGestureRecognizer.h"
TouchDownGestureRecognizer *touchDown = [[TouchDownGestureRecognizer alloc] initWithTarget:self action:@selector(handleTouchDown:)];
[yourView addGestureRecognizer:touchDown];
-(void)handleTouchDown:(TouchDownGestureRecognizer *)touchDown{
NSLog(@"Down");
}
Rapida implementazione:
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
}
}
Ecco la sintassi Swift per il 2017 da incollare:
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
}
}
Nota che questo è un sostituto immediato di UITap
. Quindi in codice come ...
func add(tap v:UIView, _ action:Selector) {
let t = UITapGestureRecognizer(target: self, action: action)
v.addGestureRecognizer(t)
}
puoi tranquillamente passare a ....
func add(hairtriggerTap v:UIView, _ action:Selector) {
let t = SingleTouchDownGestureRecognizer(target: self, action: action)
v.addGestureRecognizer(t)
}
I test mostrano che non verrà chiamato più di una volta. Funziona come un sostituto immediato; puoi semplicemente scambiare tra le due chiamate.
Usa un UILongPressGestureRecognizer e impostalo minimumPressDuration
su 0. Agirà come un touch down durante ilUIGestureRecognizerStateBegan
stato.
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()
}
}
-(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];
}
}
UIGestureRecognizerStateEnded
minimumPressDuration
può essere 0 tho.
Ecco una versione Swift simile alla risposta Objective-C di Rob Caraway .
L'idea è di utilizzare un riconoscimento di gesti a pressione prolungata con l' minimumPressDuration
impostazione a zero piuttosto che utilizzare un riconoscimento di gesti di tocco. Questo perché il riconoscimento del gesto di pressione prolungata segnala gli eventi di inizio tocco mentre il gesto di tocco 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")
}
}
}
Questa è un'altra soluzione. Crea una sottoclasse di UIControl. Puoi usarlo come UIView anche in Storyboard perché UIControl è una sottoclasse di UIView.
class TouchHandlingView: UIControl {
}
E aggiungi un obiettivo:
@IBOutlet weak var mainView: TouchHandlingView!
...
mainView.addTarget(self, action: "startAction:", forControlEvents: .TouchDown)
...
Quindi l'azione designata verrà chiamata come UIButton:
func startAction(sender: AnyObject) {
print("start")
}
Avevo bisogno della possibilità per la mia vista di avere un grilletto dei capelli, quindi non appena viene toccato risponde. L'utilizzo di entrambe le risposte @LESANG ha funzionato, così come la risposta di @RobCaraway . Il problema che ho riscontrato con entrambe le risposte è stato che ho perso la capacità di riconoscere i colpi. Avevo bisogno che la mia vista ruotasse durante lo scorrimento, ma non appena il mio dito ha toccato la vista è stato riconosciuto solo il tocco. Il tapRecognizer era troppo sensibile e non poteva distinguere tra un tocco e uno scorrimento.
Questo è quello che ho trovato in base alla risposta di @LESANG combinata con questa risposta e questa risposta .
Ho messo 6 commenti in ogni evento.
import UIKit.UIGestureRecognizerSubclass
class SingleTouchDownGestureRecognizer: UIGestureRecognizer {
var wasSwiped = false
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
guard let view = self.view else { return }
guard let touches = event.touches(for: view) else { return } // 1. compare that event in touchesBegan has touches for the view that is the same as the view to which your gesture recognizer was assigned
if touches.first != nil {
print("Finger touched!") // 2. this is when the user's finger first touches the view and is at locationA
wasSwiped = false // 3. it would seem that I didn't have to set this to false because the property was already set to false but for some reason when I didn't add this it wasn't responding correctly. Basically set this to false
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
guard let touch = touches.first else { return }
let newLocation = touch.location(in: self.view)
let previousLocation = touch.previousLocation(in: self.view)
if (newLocation.x > previousLocation.x) || (newLocation.x < previousLocation.x) {
print("finger touch went right or left") // 4. when the user's finger first touches it's at locationA. If the the user moves their finger to either the left or the right then the finger is no longer at locationA. That means it moved which means a swipe occurred so set the "wasSwiped" property to true
wasSwiped = true // 5. set the property to true because the user moved their finger
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
print("finger is no longer touching.") // 6. the user has lifted their finger off of the view. If "wasSwiped" is true then ".fail" but if it wasn't swiped then ".recognize"
if wasSwiped {
self.state = .failed
} else {
self.state = .recognized
}
}
}
E per usarlo in modo che la vista che lo utilizza ottenga la risposta del grilletto dei capelli e i gesti di scorrimento sinistro e destro .:
let tapGesture = SingleTouchDownGestureRecognizer(target: self, action: #selector(viewWasTapped(_:)))
myView.addGestureRecognizer(tapGesture)
let rightGesture = UISwipeGestureRecognizer(target: self, action: #selector(respondToSwipeGesture(recognizer:)))
rightGesture.direction = .right
myView.addGestureRecognizer(rightGesture)
let leftGesture = UISwipeGestureRecognizer(target: self, action: #selector(respondToSwipeGesture(recognizer:)))
leftGesture.direction = .left
myView.addGestureRecognizer(leftGesture)