web-dev-qa-db-fra.com

UIButton Long Press Event

Je veux émuler un long appui sur un bouton, comment puis-je faire cela? Je pense qu'une minuterie est nécessaire. Je vois UILongPressGestureRecognizer mais comment puis-je utiliser ce type?

78
Andrea

Vous pouvez commencer par créer et associer l'instance UILongPressGestureRecognizer au bouton.

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
[self.button addGestureRecognizer:longPress];
[longPress release];

Et puis implémenter la méthode qui gère le geste

- (void)longPress:(UILongPressGestureRecognizer*)gesture {
    if ( gesture.state == UIGestureRecognizerStateEnded ) {
         NSLog(@"Long Press");
    }
}

Maintenant, ce serait l'approche de base. Vous pouvez également définir la durée minimale de la presse et le niveau d'erreur tolérable. Notez également que la méthode est appelée plusieurs fois si, après avoir reconnu le geste, vous devez vérifier son état et le gérer à la fin.

154

En guise d'alternative à la réponse acceptée, cela peut être fait très facilement dans Xcode à l'aide d'Interface Builder.

Il vous suffit de faire glisser un identificateur de geste appui long depuis la bibliothèque d'objets et de le déposer au-dessus du bouton à l'endroit où vous souhaitez appuyer.

Ensuite, connectez une action de la reconnaissance de mouvements Long Press que vous venez d'ajouter, à votre contrôleur de vue, en sélectionnant l'expéditeur comme étant de type UILongPressGestureRecognizer. Dans le code de cette IBAction, utilisez ceci, qui est très similaire au code suggéré dans la réponse acceptée:

Dans Objective-C :

if ( sender.state == UIGestureRecognizerStateEnded ) {
     // Do your stuff here
}

Ou dans Swift :

if sender.state == .Ended {
    // Do your stuff here
}

Mais je dois admettre qu'après avoir essayé, je préfère la suggestion de @shengbinmeng en tant que commentaire sur la réponse acceptée, qui consistait à utiliser:

Dans Objective-C :

if ( sender.state == UIGestureRecognizerStateBegan ) {
     // Do your stuff here
}

Ou dans Swift :

if sender.state == .Began {
    // Do your stuff here
}

La différence est qu'avec Ended, vous voyez l'effet de la pression longue lorsque vous levez le doigt. Avec Began, vous voyez l'effet de la pression longue dès qu'elle est capturée par le système, avant même que vous ne retiriez le doigt de l'écran. 

22
alondono

Version rapide de la réponse acceptée

J'ai apporté la modification supplémentaire consistant à utiliser UIGestureRecognizerState.Began plutôt que .Ended car c'est probablement ce à quoi la plupart des utilisateurs s'attendent naturellement. Essayez-les tous les deux et voyez par vous-même.

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

Essaye ça:

Ajout de bouton dans viewDidLoad: comme ci-dessous

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

Appelez maintenant la méthode du geste comme ceci

-(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 
}
8
TheTiger

Pour Swift 4, la "func longPress" doit être modifiée pour que cela fonctionne:

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

Je pense que vous avez besoin de ma solution.

vous devriez avoir ce code pour une seule presse

- (IBAction)buttonDidPress:(id)sender {
    NSLog("buttonDidPress");
}

d'abord, ajoutez un geste long au bouton 

- (void)viewWillAppear:(BOOL)animated
{
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(buttonDidLongPress:)];
    [self.button addGestureRecognizer:longPress];
}

puis appelez l'événement de presse unique à plusieurs reprises si le geste de presse long est reconnu.

- (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;
    }
}
3
Jerry Juang

J'ai une sous-classe UIButton pour mon application, donc j'ai sorti mon implémentation. Vous pouvez l'ajouter à votre sous-classe ou vous pouvez tout aussi bien le recoder en tant que catégorie UIButton.

Mon objectif était d’appuyer longuement sur mon bouton sans encombrer mes contrôleurs de vue de tout le code. J'ai décidé que l'action devrait être appelée lorsque l'état de reconnaissance de geste commence.

Il y a un avertissement qui sort que je n'ai jamais pris la peine de résoudre. Dit que c'est une fuite possible, pensais avoir testé le code et qu'il ne fuyait pas.

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

Pour affecter l'action, ajoutez cette ligne à votre méthode viewDidLoad.

[_myLongButton addLongPressTarget:0.75 target:self selector:@selector(longPressAction:)];

L'action doit être définie comme toutes les IBActions (sans l'IBAction).

- (void)longPressAction:(id)sender {
    // sender is the button
}
0
Dan Loughney

Aucun n'a fonctionné, c'est pourquoi j'ai essayé d'écrire le code d'impression longue presse dans IBAction ou le clic sur le bouton de storyboard dans Controller au lieu d'écrire dans viewDidLoad

- (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];

}
0
karan