【问题标题】:UIButton Long Press EventUIButton 长按事件
【发布时间】:2011-09-04 23:31:18
【问题描述】:

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

【问题讨论】:

    标签: ios objective-c uibutton long-press


    【解决方案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

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

    【讨论】:

    • 似乎它在 Swift 中不起作用。得到错误“二元运算符'|'不能应用于两个 'UIControl.Event' 操作数"
    【解决方案2】:

    试试这个:

    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 的错误标签。有什么解决办法吗?
    【解决方案3】:

    已接受答案的 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")
        }
    }
    

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

        没有工作,因此我尝试在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];
        
        }
        

        【讨论】:

          【解决方案6】:

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

          只需从对象库中拖出一个长按手势识别器,然后将其放在您想要进行长按操作的按钮顶部。

          接下来,将刚刚添加的 Long Press Gesture Recognizer 中的一个 Action 连接到您的视图控制器,选择发送者为 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,您可以在系统捕捉到长按后立即看到长按的效果,甚至在您将手指从屏幕上移开之前。

          【讨论】:

            【解决方案7】:

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

            【讨论】:

              【解决方案8】:

              我认为你需要我的解决方案。

              你应该有这个代码来单按

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

              【讨论】:

              • 您不应该在viewWillAppear 生命周期事件期间添加UIGestureRecognizer,因为每当视图出现时,都会添加另一个手势识别器。这应该在初始化期间调用的私有方法中完成。
              【解决方案9】:

              您可以从创建 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 中收到很多事件
              • 您可能想使用if(gesture.state == UIGestureRecognizerStateBegan),因为用户希望在他们仍然按下时(状态开始)而不是释放时(结束)时发生一些事情。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2023-04-02
              • 1970-01-01
              • 2011-04-02
              • 1970-01-01
              • 2014-05-24
              相关资源
              最近更新 更多