UIButton长按事件

发布于 2024-11-10 05:49:09 字数 91 浏览 5 评论 0原文

我想模拟长按按钮,我该怎么做?我认为需要一个计时器。 我看到 UILongPressGestureRecognizer 但如何利用这种类型?

I want to emulate a long a press button, how can I do this? I think a timer is needed.
I see UILongPressGestureRecognizer but how can I utilize this type?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

澉约 2024-11-17 05:49:09

您可以首先创建 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");
    }
}

现在这将是基本方法。您还可以设置按压的最短持续时间以及可容忍的错误量。另请注意,如果您在识别手势后,该方法会被调用几次,因此如果您想在手势结束时执行某些操作,则必须检查其状态并进行处理。

You can start off by creating and attaching the UILongPressGestureRecognizer instance to the button.

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

And then implement the method that handles the gesture

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

Now this would be the basic approach. You can also set the minimum duration of the press and how much error is tolerable. And also note that the method is called few times if you after recognizing the gesture so if you want to do something at the end of it, you will have to check its state and handle it.

淡墨 2024-11-17 05:49:09

作为已接受答案的替代方案,可以使用 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提出的建议作为对已接受答案的评论,即使用:

In Objective-C:

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

或者 in Swift

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

不同之处在于,使用 Ended 时,您可以在抬起手指时看到长按的效果。使用Began,只要系统捕获到长按,甚至在您将手指从屏幕上抬起之前,您就可以看到长按的效果。

As an alternative to the accepted answer, this can be done very easily in Xcode using Interface Builder.

Just drag a Long Press Gesture Recognizer from the Object Library and drop it on top of the button where you want the long press action.

Next, connect an Action from the Long Press Gesture Recognizer just added, to your view controller, selecting the sender to be of type UILongPressGestureRecognizer. In the code of that IBAction use this, which is very similar to the code suggested in the accepted answer:

In Objective-C:

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

Or in Swift:

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

But I have to admit that after trying it, I prefer the suggestion made by @shengbinmeng as a comment to the accepted answer, which was to use:

In Objective-C:

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

Or in Swift:

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

The difference is that with Ended, you see the effect of the long press when you lift your finger. With Began, you see the effect of the long press as soon as the long press is caught by the system, even before you lift the finger off the screen.

跨年 2024-11-17 05:49:09

已接受答案的 Swift 版本

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

Swift version of the accepted answer

I made the additional modification of using UIGestureRecognizerState.Began rather than .Ended since that is probably what most users would naturally expect. Try them both and see for yourself, though.

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")
    }
}
£冰雨忧蓝° 2024-11-17 05:49:09

试试这个:

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 
}

Try this:

Adding button in viewDidLoad: like below

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

Now call the gesture method like this

-(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 
}
绳情 2024-11-17 05:49:09

我想你需要我的解决方案。

您应该首先具有用于单击的代码

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

I think you need my solution.

you should have this code for single press

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

first, add long press gesture to button

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

then call single press event repeatedly if long press gesture is recognized.

- (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;
    }
}
也只是曾经 2024-11-17 05:49:09

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

For Swift 4, the "func longPress" needs to be changed to make it work:

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")
    }
}
暮年 2024-11-17 05:49:09

一行回答,无需手势:

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

详细信息:
这会在三个事件上触发您的目标:
1- 一旦手指触及按钮:UIControlEventTouchDown。这捕获了长按开始。
2& 3-当用户抬起手指时:UIControlEventTouchUpOutside & UIControlEventTouchUpInside。这捕获用户按下的结束。

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

如果需要,您可以添加更多中间事件,请在此处查看所有事件 https://developer.apple.com/documentation/uikit/uicontrolevents?language=objc

在故事板中:
将您的按钮连接到 3 个事件,而不仅仅是 Storyboard 选择的默认事件(Touch Up Inside)。

One-line answer, with no gestures:

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

Details:
This triggers your target on three events:
1- Immediately once finger touches down the button: UIControlEventTouchDown. This captures long presses start.
2 & 3- When user lifts finger up: UIControlEventTouchUpOutside & UIControlEventTouchUpInside. This captures end of the user press.

Note: this works well if you don't care about the extra info provided by the gesture recognizer (e.g. location of touch, etc.)

You can add more intermediate events if needed see them all here https://developer.apple.com/documentation/uikit/uicontrolevents?language=objc.

In Storyboard:
Connect your button to the 3 events, not just the default one that Storyboard selects (Touch Up Inside).

3 events in storyboard

彩扇题诗 2024-11-17 05:49:09

我的应用程序有一个子类 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
}

I have a subclassed UIButton for my app, so I've pulled out my implementation. You can add this to your subclass or this could just as easily be recoded as a UIButton category.

My goal was to add the long press to my button without cluttering my view controllers with all of the code. I've decided that the action should be called when the gesture recognizer state begins.

There is a warning that comes out that I've never bothered to solve. Says it is a possible leak, thought I've tested the code and it doesn't leak.

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

To assign the action add this line to your viewDidLoad method.

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

The action should be defined like all IBActions (without the IBAction).

- (void)longPressAction:(id)sender {
    // sender is the button
}
忆离笙 2024-11-17 05:49:09

没有一个有效,因此我尝试在 IBAction 中编写长按代码或在 Controller 中从 storyboard 单击按钮,而不是在 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];

}

None worked hence I tried writing longpress code in IBAction or button click from storyboard in Controller instead of writing in 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];

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文