UIButton Long Press Event

86

Ich möchte einen langen Druckknopf emulieren. Wie kann ich das tun? Ich denke, ein Timer wird benötigt. Ich sehe, UILongPressGestureRecognizeraber wie kann ich diesen Typ verwenden?

Andrea
quelle

Antworten:

160

Sie können beginnen, indem Sie die UILongPressGestureRecognizerInstanz erstellen und an die Schaltfläche anhängen .

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

Implementieren Sie dann die Methode, die die Geste verarbeitet

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

Dies wäre nun der grundlegende Ansatz. Sie können auch die Mindestdauer der Druckmaschine und die Toleranz für Fehler festlegen. Beachten Sie auch, dass die Methode einige Male aufgerufen wird, wenn Sie die Geste erkannt haben. Wenn Sie also am Ende etwas tun möchten, müssen Sie den Status überprüfen und damit umgehen.

Deepak Danduprolu
quelle
Super! Vielen Dank! Übrigens: Das if (gesture.state == UIGestureRecognizerStateEnded) ist sehr wichtig, sonst erhalten Sie eine Menge Ereignisse in Ihrer longPress void
RecycleRobot
29
Möglicherweise möchten Sie verwenden if(gesture.state == UIGestureRecognizerStateBegan), da der Benutzer erwartet, dass etwas passiert, wenn er noch drückt (der Status Began), und nicht, wenn er loslässt (Beendet).
Shenbbinmeng
28

Als Alternative zur akzeptierten Antwort kann dies in Xcode mit Interface Builder sehr einfach durchgeführt werden.

Ziehen Sie einfach einen Gestenerkenner für langes Drücken aus der Objektbibliothek und legen Sie ihn oben auf der Schaltfläche ab, auf der Sie die Aktion für langes Drücken ausführen möchten.

Verbinden Sie als Nächstes eine Aktion aus dem gerade hinzugefügten Long Press Gesture Recognizer mit Ihrem Ansichts-Controller und wählen Sie den Absender aus, der vom Typ sein soll UILongPressGestureRecognizer. IBActionVerwenden Sie im Code dieses Codes Folgendes, das dem in der akzeptierten Antwort vorgeschlagenen Code sehr ähnlich ist:

In Ziel-C :

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

Oder in Swift :

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

Aber ich muss zugeben, dass ich nach dem Versuch den Vorschlag von @shengbinmeng als Kommentar der akzeptierten Antwort vorziehe, die verwendet werden sollte:

In Ziel-C :

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

Oder in Swift :

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

Der Unterschied besteht darin, dass EndedSie beim Heben des Fingers den Effekt des langen Drucks sehen. Mit sehen BeganSie den Effekt des langen Drucks, sobald der lange Druck vom System erfasst wird, noch bevor Sie den Finger vom Bildschirm heben.

Alondono
quelle
18

Schnelle Version der akzeptierten Antwort

Ich habe die zusätzliche Modifikation der Verwendung vorgenommen, UIGestureRecognizerState.Begananstatt .Endeddass dies wahrscheinlich das ist, was die meisten Benutzer natürlich erwarten würden. Probieren Sie beide aus und überzeugen Sie sich selbst.

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

Versuche dies:

Hinzufügen einer Schaltfläche viewDidLoad:wie unten

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

Rufen Sie nun die Gestenmethode so auf

-(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 
}
TheTiger
quelle
recognizer.view.taggibt mir falsches Tag von UIButton angeklickt. Irgendeine Lösung?
Rohan-Patel
3

Ich denke du brauchst meine Lösung.

Sie sollten diesen Code für einmaliges Drücken haben

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

Fügen Sie zunächst eine lange Druckgeste zur Taste hinzu

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

Rufen Sie dann wiederholt ein einzelnes Presseereignis auf, wenn eine lange Druckgeste erkannt wird.

- (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;
    }
}
Jerry Juang
quelle
Sie sollten UIGestureRecognizerdas viewWillAppearEreignis während des Lebenszyklus nicht hinzufügen, da bei jeder Anzeige eine weitere Gestenerkennung hinzugefügt wird. Dies sollte in einer privaten Methode erfolgen, die während der Initialisierung aufgerufen wird.
WikipediaBrown
3

Für Swift 4 muss die "func longPress" geändert werden, damit es funktioniert:

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

Einzeilige Antwort ohne Gesten:

[btn addTarget:self action:@selector(handleTouch:) forControlEvents:UIControlEventTouchDown | UIControlEventTouchUpInside | UIControlEventTouchUpOutside];

Details: Dies löst Ihr Ziel bei drei Ereignissen aus: 1- Sobald der Finger die Taste berührt : UIControlEventTouchDown. Dies erfasst den Start langer Druckvorgänge. 2 & 3- Wenn der Benutzer den Finger hebt: UIControlEventTouchUpOutside& UIControlEventTouchUpInside. Dies erfasst das Ende der Benutzerpresse.

Hinweis: Dies funktioniert gut, wenn Sie sich nicht um die zusätzlichen Informationen kümmern, die vom Gestenerkenner bereitgestellt werden (z. B. Ort der Berührung usw.).

Sie können bei Bedarf weitere Zwischenereignisse hinzufügen. Alle finden Sie hier https://developer.apple.com/documentation/uikit/uicontrolevents?language=objc .

In Storyboard: Verbinden Sie Ihre Schaltfläche mit den 3 Ereignissen, nicht nur mit dem Standardereignis, das Storyboard auswählt (Touch Up Inside).

3 Ereignisse im Storyboard

CSawy
quelle
0

Ich habe einen untergeordneten UIButton für meine App, daher habe ich meine Implementierung herausgezogen. Sie können dies zu Ihrer Unterklasse hinzufügen oder es kann genauso einfach neu codiert werden wie eine UIButton-Kategorie.

Mein Ziel war es, den langen Druck auf meine Schaltfläche zu übertragen, ohne meine View Controller mit dem gesamten Code zu überladen. Ich habe beschlossen, dass die Aktion aufgerufen werden soll, wenn der Status der Gestenerkennung beginnt.

Es kommt eine Warnung heraus, die ich nie gelöst habe. Sagt, es ist ein mögliches Leck, dachte, ich habe den Code getestet und es leckt nicht.

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

Um die Aktion zuzuweisen, fügen Sie diese Zeile Ihrer viewDidLoad-Methode hinzu.

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

Die Aktion sollte wie alle IBActions definiert werden (ohne die IBAction).

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

Keiner arbeitete daher Longpress - Code in Ich habe versucht , zu schreiben IBActionoder Button - Klick aus storyboardin Controlleranstelle des Schreibens inviewDidLoad

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

}
Karan
quelle