Событие длительного нажатия UIButton

86

Я хочу сымитировать долгое нажатие кнопки, как мне это сделать? Думаю нужен таймер. Понятно, UILongPressGestureRecognizerно как я могу использовать этот тип?

Андреа
источник

Ответы:

160

Вы можете начать с создания и прикрепления UILongPressGestureRecognizerэкземпляра к кнопке.

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

А затем реализуйте метод, обрабатывающий жест

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

Теперь это будет основной подход. Вы также можете установить минимальную продолжительность печати и допустимую ошибку. Также обратите внимание, что метод вызывается несколько раз, если вы распознаете жест, поэтому, если вы хотите что-то сделать в конце, вам нужно будет проверить его состояние и обработать его.

Дипак Дандупролу
источник
Супер! Благодарность! Кстати: if (gesture.state == UIGestureRecognizerStateEnded) очень важен, иначе вы получите много событий в вашем longPress void
RecycleRobot
29
Возможно, вы захотите использовать if(gesture.state == UIGestureRecognizerStateBegan), потому что пользователь ожидает, что что-то произойдет, когда они все еще нажимают (состояние Начато), а не когда они отпускают (Завершено).
shengbinmeng
28

В качестве альтернативы принятому ответу это можно очень легко сделать в Xcode с помощью Interface Builder.

Просто перетащите распознаватель жестов при длительном нажатии из библиотеки объектов и поместите его поверх кнопки, где вы хотите выполнить длительное нажатие.

Затем подключите действие из только что добавленного распознавателя жестов длительного нажатия к вашему контроллеру представления, выбрав отправителя, который должен иметь тип UILongPressGestureRecognizer. В коде этогоIBAction используйте это, что очень похоже на код, предложенный в принятом ответе:

В Objective-C :

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

Или в Swift :

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

Но я должен признать, что после попытки я предпочитаю предложение @shengbinmeng в качестве комментария к принятому ответу, который должен был использовать:

В Objective-C :

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

Или в Swift :

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

Разница в том, что с помощью Ended, вы видите эффект длительного нажатия, когда поднимаете палец. С помощью Began, вы видите эффект длительного нажатия, как только долгое нажатие улавливается системой, даже до того, как вы уберете палец с экрана.

Alondono
источник
18

Быстрая версия принятого ответа

Я сделал дополнительную модификацию using UIGestureRecognizerState.Began, .Endedтак как это, вероятно, то, чего, естественно, ожидает большинство пользователей. Однако попробуйте их оба и убедитесь сами.

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
источник
9

Попробуй это:

Добавление кнопки, viewDidLoad:как показано ниже

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

Теперь вызовите метод жеста следующим образом

-(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
источник
recognizer.view.tagдает мне неправильный тег UIButton. Любое решение?
rohan-patel
3

Думаю, тебе нужно мое решение.

у вас должен быть этот код для однократного нажатия

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

сначала добавьте жест долгого нажатия на кнопку

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

затем повторно вызовите событие однократного нажатия, если распознается жест долгого нажатия.

- (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во время viewWillAppearжизненного цикла, потому что всякий раз, когда появляется представление, будет добавлен другой распознаватель жестов. Это должно быть сделано в частном методе, который вызывается во время инициализации.
WikipediaBrown
3

Для Swift 4 необходимо изменить "func longPress", чтобы он работал:

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

Однострочный ответ, без жестов:

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

Подробности: Это вызывает вашу цель на три события: 1- Сразу , как только палец касается вниз кнопок: UIControlEventTouchDown. Это фиксирует начало долгого нажатия. 2 и 3- Когда пользователь поднимает палец вверх: UIControlEventTouchUpOutside& UIControlEventTouchUpInside. Это фиксирует конец нажатия пользователем.

Примечание: это хорошо работает, если вам не важна дополнительная информация, предоставляемая распознавателем жестов (например, местоположение касания и т. Д.)

При необходимости вы можете добавить дополнительные промежуточные события, см. Их все здесь https://developer.apple.com/documentation/uikit/uicontrolevents?language=objc .

В раскадровке: подключите кнопку к трем событиям, а не только к тому, которое по умолчанию выбирает раскадровка (Touch Up Inside).

3 события в раскадровке

CSawy
источник
0

У меня есть подкласс UIButton для моего приложения, поэтому я вытащил свою реализацию. Вы можете добавить это в свой подкласс, или это можно так же легко перекодировать, как категорию UIButton.

Моей целью было добавить долгое нажатие на мою кнопку, не загромождая контроллеры представления всем кодом. Я решил, что действие должно вызываться, когда начинается состояние распознавателя жестов.

Появляется предупреждение, которое я никогда не решал. Говорит, что это возможная утечка, думал, что тестировал код, и утечки нет.

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

Чтобы назначить действие, добавьте эту строку в свой метод viewDidLoad.

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

Действие должно быть определено как все IBActions (без IBAction).

- (void)longPressAction:(id)sender {
    // sender is the button
}
Дэн Лоуни
источник
0

Никто не работал , следовательно , я пытался писать код longpress в IBActionили кнопку мыши из storyboardв Controllerвместо того , чтобы писать в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];

}
Каран
источник