Evento di pressione prolungata del pulsante UIB


86

Voglio emulare a lungo un pulsante di pressione, come posso farlo? Penso che sia necessario un timer. Vedo UILongPressGestureRecognizerma come posso utilizzare questo tipo?

Risposte:


160

Puoi iniziare creando e allegando l' UILongPressGestureRecognizeristanza 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.


Super! Grazie! A proposito: if (gesture.state == UIGestureRecognizerStateEnded) è molto importante, altrimenti avrai molti eventi nel tuo void di
longPress

29
Forse vuoi usare if(gesture.state == UIGestureRecognizerStateBegan), perché l'utente si aspetta che accada qualcosa quando sta ancora premendo (lo stato Began), non quando rilascia (Ended).
shengbinmeng

28

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 IBActionuso 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.


18

Versione rapida della risposta accettata

Ho apportato la modifica aggiuntiva di utilizzare UIGestureRecognizerState.Beganpiuttosto che .Endedpoiché è 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")
    }
}

8

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.tagmi dà il tag sbagliato di UIButton cliccato. Qualche soluzione?
rohan-patel

3

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

Non dovresti aggiungere UIGestureRecognizerdurante l' viewWillAppearevento 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.
Wikipedia

3

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

1

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).

3 eventi nello storyboard


0

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
}

0

Nessuno ha funzionato, quindi ho provato a scrivere codice longpress IBActiono fare clic sul pulsante da storyboarddentro Controllerinvece 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];

}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.