UIButton长按事件


86

我想模仿长按按钮,该怎么办?我认为需要一个计时器。我知道了,UILongPressGestureRecognizer但是我该如何利用这种类型?

Answers:


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

29
您可能要使用if(gesture.state == UIGestureRecognizerStateBegan),因为用户希望在他们仍然按下(状态为Began)时发生某些事情,而不是在释放时(Ended)发生某件事。
升斌梦2014年

28

作为公认答案的替代方法,这可以使用Interface Builder在Xcode中轻松完成。

只需将“长按手势识别器”从“对象库”中拖放到想要长按动作的按钮顶部即可。

接下来,将刚添加的“长按手势识别器”中的“动作”连接到视图控制器,选择类型为“发件人”的发件人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,您会在系统抓住长按后立即看到长按的效果,甚至在手指离开屏幕之前也是如此。


18

接受答案的Swift版本

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

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给我的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;
    }
}

您不应UIGestureRecognizerviewWillAppear生命周期事件中添加,因为每当视图出现时,都会添加另一个手势识别器。这应该在初始化期间调用的私有方法中完成。
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-当用户抬起手指时:UIControlEventTouchUpOutsideUIControlEventTouchUpInside。这捕获了用户按下的结尾。

注意:如果您不关心手势识别器提供的额外信息(例如,触摸的位置等),则此方法很好用

如果需要,您可以添加更多中间事件,请参见https://developer.apple.com/documentation/uikit/uicontrolevents?language=objc

在Storyboard中: 将您的按钮连接到3个事件,而不仅仅是Storyboard选择的默认事件(Touch 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:)];

应该像所有IBAction(没有IBAction)一样定义该动作。

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

0

没有任何效果,因此我尝试在其中写入longpress代码IBAction或从中单击按钮storyboardController而不是写入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];

}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.