UIButton Long Press Event


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використовує це, дуже схоже на код, запропонований у прийнятій відповіді:

У цілі-C :

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

Або в Свіфт :

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

Але я повинен визнати, що спробувавши, я віддаю перевагу пропозиції @shengbinmeng як коментар до прийнятої відповіді, яка мала використовуватись:

У цілі-C :

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

Або в Свіфт :

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

Різниця полягає в тому, що з Ended, ви бачите ефект тривалого натискання, коли ви піднімаєте палець. З цим Beganви бачите ефект тривалого натискання, як тільки система натискає на довге натискання, ще до того, як ви відведете палець від екрана.


18

Швидка версія прийнятої відповіді

Я зробив додаткову модифікацію використання, 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")
    }
}

8

Спробуйте це:

Додавання кнопки, 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 
}

recognizer.view.tagдає мені неправильний тег натиснутого кнопки UIB. Будь-яке рішення?
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події життєвого циклу, оскільки кожного разу, коли з’являється представлення, буде додано інший розпізнавач жестів. Це слід робити в приватному методі, який викликається під час ініціалізації.
Wikipedia

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 .

У Storyboard: підключіть свою кнопку до 3 подій, а не лише до тієї, що вибрана за замовчуванням (Story Up Inside).

3 події в раскадровці


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

}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.