Voglio emulare a lungo un pulsante di pressione, come posso farlo? Penso che sia necessario un timer. Vedo UILongPressGestureRecognizer
ma come posso utilizzare questo tipo?
Risposte:
Puoi iniziare creando e allegando l' UILongPressGestureRecognizer
istanza al pulsante.
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
[self.button addGestureRecognizer:longPress];
[longPress release];
E poi implementa il metodo che gestisce il gesto
- (void)longPress:(UILongPressGestureRecognizer*)gesture {
if ( gesture.state == UIGestureRecognizerStateEnded ) {
NSLog(@"Long Press");
}
}
Ora questo sarebbe l'approccio di base. È inoltre possibile impostare la durata minima della stampa e l'entità dell'errore tollerabile. E nota anche che il metodo viene chiamato poche volte se dopo aver riconosciuto il gesto, quindi se vuoi fare qualcosa alla fine di esso, dovrai controllarne lo stato e gestirlo.
if(gesture.state == UIGestureRecognizerStateBegan)
, perché l'utente si aspetta che accada qualcosa quando sta ancora premendo (lo stato Began), non quando rilascia (Ended).
In alternativa alla risposta accettata, questo può essere fatto molto facilmente in Xcode utilizzando Interface Builder.
Basta trascinare un Riconoscitore di gesti a pressione prolungata dalla Libreria oggetti e rilasciarlo sopra il pulsante dove si desidera l'azione di pressione prolungata.
Quindi, collega un'azione dal Riconoscitore di gesti a pressione prolungata appena aggiunto, al controller della vista, selezionando il mittente di tipo UILongPressGestureRecognizer
. Nel codice di tale IBAction
uso questo, che è molto simile al codice suggerito nella risposta accettata:
In Objective-C :
if ( sender.state == UIGestureRecognizerStateEnded ) {
// Do your stuff here
}
O in Swift :
if sender.state == .Ended {
// Do your stuff here
}
Ma devo ammettere che dopo averlo provato, preferisco il suggerimento di @shengbinmeng come commento alla risposta accettata, che doveva usare:
In Objective-C :
if ( sender.state == UIGestureRecognizerStateBegan ) {
// Do your stuff here
}
O in Swift :
if sender.state == .Began {
// Do your stuff here
}
La differenza è che con Ended
, vedi l'effetto della pressione prolungata quando sollevi il dito. Con Began
, si vede l'effetto della pressione prolungata non appena la pressione prolungata viene rilevata dal sistema, anche prima di sollevare il dito dallo schermo.
Ho apportato la modifica aggiuntiva di utilizzare UIGestureRecognizerState.Began
piuttosto che .Ended
poiché è probabilmente ciò che la maggior parte degli utenti si aspetterebbe naturalmente. Provali entrambi e guarda di persona, però.
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// add gesture recognizer
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPress(_:)))
self.button.addGestureRecognizer(longPress)
}
func longPress(gesture: UILongPressGestureRecognizer) {
if gesture.state == UIGestureRecognizerState.began {
print("Long Press")
}
}
@IBAction func normalButtonTap(sender: UIButton) {
print("Button tapped")
}
}
Prova questo:
Aggiunta di un pulsante viewDidLoad:
come di seguito
-(void)viewDidLoad {
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setTag:1]; //you can set any integer value as tag number
btn.title = @"Press Me";
[btn setFrame:CGRectMake(50.0, 50.0, 60.0, 60.0)];
// now create a long press gesture
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPressTap:)];
[btn addGestureRecognizer:longPress];
}
Ora chiama il metodo dei gesti in questo modo
-(void)longPressTap:(id)sender {
UIGestureRecognizer *recognizer = (UIGestureRecognizer*) sender
// Recogniser have all property of button on which you have clicked
// Now you can compare button's tag with recogniser's view.tag
// View frame for getting the info on which button the click event happened
// Then compare tag like this
if(recognizer.view.tag == 1) {
// Put your button's click code here
}
// And you can also compare the frame of your button with recogniser's view
CGRect btnRect = CGRectMake(50.0, 50.0, 60.0, 60.0);
if(recogniser.view.frame == btnRect) {
//put your button's click code here
}
// Remember frame comparing is alternative method you don't need to write frame comparing code if you are matching the tag number of button
}
recognizer.view.tag
mi dà il tag sbagliato di UIButton cliccato. Qualche soluzione?
Penso che tu abbia bisogno della mia soluzione.
dovresti avere questo codice per la singola stampa
- (IBAction)buttonDidPress:(id)sender {
NSLog("buttonDidPress");
}
per prima cosa, aggiungi un gesto di pressione prolungata al pulsante
- (void)viewWillAppear:(BOOL)animated
{
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(buttonDidLongPress:)];
[self.button addGestureRecognizer:longPress];
}
quindi chiamare ripetutamente l'evento di stampa singola se viene riconosciuto il gesto di pressione lunga.
- (void)buttonDidLongPress:(UILongPressGestureRecognizer*)gesture
{
switch (gesture.state) {
case UIGestureRecognizerStateBegan:
{
self.timer = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(buttonDidPress:) userInfo:nil repeats:YES];
NSRunLoop * theRunLoop = [NSRunLoop currentRunLoop];
[theRunLoop addTimer:self.timer forMode:NSDefaultRunLoopMode];
}
break;
case UIGestureRecognizerStateEnded:
{
[self.timer invalidate];
self.timer = nil;
}
break;
default:
break;
}
}
UIGestureRecognizer
durante l' viewWillAppear
evento del ciclo di vita perché ogni volta che viene visualizzata la vista, verrà aggiunto un altro riconoscimento dei gesti. Questa operazione dovrebbe essere eseguita in un metodo privato chiamato durante l'inizializzazione.
Per Swift 4, la "func longPress" deve essere modificata per farlo funzionare:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// add guesture recognizer
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPress(_:)))
self.button.addGestureRecognizer(longPress)
}
@objc func longPress(_ guesture: UILongPressGestureRecognizer) {
if guesture.state == UIGestureRecognizerState.began {
print("Long Press")
}
}
@IBAction func normalButtonTap(sender: UIButton) {
print("Button tapped")
}
}
Risposta in una riga, senza gesti:
[btn addTarget:self action:@selector(handleTouch:) forControlEvents:UIControlEventTouchDown | UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
Dettagli:
Questo innesca il tuo obiettivo su tre eventi: 1- immediatamente una volta che tocchi dito verso il basso il pulsante: UIControlEventTouchDown
. Questo cattura l'inizio di pressioni lunghe. 2 e 3- Quando l'utente solleva il dito: UIControlEventTouchUpOutside
&UIControlEventTouchUpInside
. Questo cattura la fine della stampa dell'utente.
Nota: questo funziona bene se non ti interessano le informazioni extra fornite dal riconoscimento dei gesti (ad es. Posizione del tocco, ecc.)
Puoi aggiungere altri eventi intermedi, se necessario, vederli tutti qui https://developer.apple.com/documentation/uikit/uicontrolevents?language=objc .
Nello Storyboard: collega il tuo pulsante ai 3 eventi, non solo a quello predefinito selezionato dallo Storyboard (Ritocco all'interno).
Ho un UIButton sottoclasse per la mia app, quindi ho ritirato la mia implementazione. Puoi aggiungerlo alla tua sottoclasse o potrebbe essere facilmente ricodificato come una categoria UIButton.
Il mio obiettivo era aggiungere la pressione prolungata al mio pulsante senza ingombrare i miei controller di visualizzazione con tutto il codice. Ho deciso che l'azione dovrebbe essere chiamata quando inizia lo stato di riconoscimento dei gesti.
Viene fuori un avvertimento che non mi sono mai preso la briga di risolvere. Dice che è una possibile perdita, pensavo di aver testato il codice e non ha perdite.
@interface MYLongButton ()
@property (nonatomic, strong) UILongPressGestureRecognizer *gestureRecognizer;
@property (nonatomic, strong) id gestureRecognizerTarget;
@property (nonatomic, assign) SEL gestureRecognizerSelector;
@end
@implementation MYLongButton
- (void)addLongPressTarget:(CGFloat)interval target:(id)target action:(SEL)selector
{
_gestureRecognizerTarget = target;
_gestureRecognizerSelector = selector;
_gestureRecognizer = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(handleLongPressGestureRecognizer:)];
_gestureRecognizer.minimumPressDuration = interval;
[self addGestureRecognizer:_gestureRecognizer];
}
- (void)handleLongPressGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
NSAssert([_gestureRecognizerTarget respondsToSelector:_gestureRecognizerSelector], @"target does not respond to selector");
self.highlighted = NO;
// warning on possible leak -- can anybody fix it?
[_gestureRecognizerTarget performSelector:_gestureRecognizerSelector withObject:self];
}
}
Per assegnare l'azione aggiungi questa riga al tuo metodo viewDidLoad.
[_myLongButton addLongPressTarget:0.75 target:self selector:@selector(longPressAction:)];
L'azione dovrebbe essere definita come tutte le IBAction (senza IBAction).
- (void)longPressAction:(id)sender {
// sender is the button
}
Nessuno ha funzionato, quindi ho provato a scrivere codice longpress IBAction
o fare clic sul pulsante da storyboard
dentro Controller
invece di scrivereviewDidLoad
- (IBAction)btnClick:(id)sender {
tag = (int)((UIButton *)sender).tag;
// Long press here instead of in viewDidLoad
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
longPress.cancelsTouchesInView = NO;
[sender addGestureRecognizer:longPress];
}