【问题标题】:iOS Detect tap down and touch up of a UIViewiOS 检测 UIView 的点击和触摸
【发布时间】:2013-11-05 20:32:53
【问题描述】:

我遇到了一个问题,即确定如何检测 UIView 被触碰和 UIView 被点击。当它被按下时,我希望 UIView 改变它的背景颜色。当它被触摸时,我希望 UIView 执行某些任务。我想知道如何解决这个问题。

-(void)viewDidLoad
{        
    UITapGestureRecognizer *dismissGestureRecognition = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDismissDoubleTap:)];
    dismissGestureRecognition.numberOfTapsRequired = 1;
    [sectionDismissDoubleView addGestureRecognizer:dismissGestureRecognition];

    UITapGestureRecognizer *dismissGestureDownRecognition = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissGestureDownRecognition:)];
    dismissGestureRecognition.numberOfTouchesRequired = 1;
    [sectionDismissDoubleView addGestureRecognizer:dismissGestureDownRecognition];
}

- (void)handleDismissDoubleTap:(UIGestureRecognizer*)tap {
    SettingsDismissDoubleViewController *settingsDouble = [[SettingsDismissDoubleViewController alloc] initWithNibName:@"SettingsDismissDoubleViewController" bundle:nil];
    [self.navigationController pushViewController:settingsDouble animated:YES];
}

- (void)dismissGestureDownRecognition:(UIGestureRecognizer*)tap {
    NSLog(@"Down");
}

【问题讨论】:

    标签: ios uitapgesturerecognizer


    【解决方案1】:

    首先,通过您的选择器handleDismissDoubleTap:,我假设您正在寻找双击关闭。为此,您应该这样做:dismissGestureRecognition.numberOfTapsRequired = 2;

    其次,如果您所说的触摸是指长时间的点击(或“点击并按住”)手势,您应该使用UILongPressGestureRecognizer 而不是UITapGestureRecognizer

    【讨论】:

      【解决方案2】:

      在每个 UIControl 子类(UIButton 等)中,您都可以使用它来订阅一组特定的 UIControlEvent:

      addTarget:action:forControlEvents
      

      您应该为UIControLeventTouchDock和UIControLeventTouchUpInside事件的另一个目标/选择器添加目标。

      UIControl reference

      【讨论】:

      • 问题是关于 uiview 而不是 uicontrol
      【解决方案3】:

      手势识别器可能对你想要的东西来说太过分了。您可能只想使用-touchesBegan:withEvent:-touchesEnded:withEvent: 的组合。

      这是有缺陷的,但它应该让你知道你想做什么。

      - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
      {
          self.touchDown = YES;
          self.backgroundColor = [UIColor redColor];
      }
      
      - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
      {
          // Triggered when touch is released
          if (self.isTouchDown) {
              self.backgroundColor = [UIColor whiteColor];
              self.touchDown = NO;
          }
      }
      
      - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
      {
          // Triggered if touch leaves view
          if (self.isTouchDown) {
              self.backgroundColor = [UIColor whiteColor];
              self.touchDown = NO;
          }
      }
      

      此代码应放入您创建的UIView 的自定义子类中。然后使用此自定义视图类型而不是 UIView,您将获得触摸处理。

      【讨论】:

      • 子类化 UIView 来实现这一点是保持父视图可滚动的好方法。
      【解决方案4】:

      感谢Holly's answer 我建立了一个ButtonView 便利类。

      编辑:正如answer 所说,UILongPressGestureRecognizer 反应更快,所以我更新了我的课程。

      用法:

      let btn = ButtonView()
      btn.onNormal = { btn.backgroundColor = .clearColor() }
      btn.onPressed = { btn.backgroundColor = .blueColor() }
      btn.onReleased = yourAction // Function to be called
      

      类:

      /** View that can be pressed like a button */
      
      import UIKit
      
      class ButtonView : UIView {
      
          /* Called when the view goes to normal state (set desired appearance) */
          var onNormal = {}
          /* Called when the view goes to pressed state (set desired appearance) */
          var onPressed = {}
          /* Called when the view is released (perform desired action) */
          var onReleased = {}
      
          override init(frame: CGRect)
          {
              super.init(frame: frame)
      
              let recognizer = UILongPressGestureRecognizer(target: self, action: Selector("touched:"))
              recognizer.delegate = self
              recognizer.minimumPressDuration = 0.0
              addGestureRecognizer(recognizer)
              userInteractionEnabled = true
      
              onNormal()
          }
      
          func touched(sender: UILongPressGestureRecognizer)
          {
              if sender.state == .Began {
                  onPressed(self)
              } else if sender.state == .Ended {
                  onNormal(self)
                  onReleased()
              }
          }
      
          required init?(coder aDecoder: NSCoder) {
              fatalError("init(coder:) has not been implemented")
          }
      }
      

      【讨论】:

      • 我终于改成了使用UIControl的版本,反应不那么快,但还有其他优点:如果你拖到按钮上,你可以在下面拖一个UIScrollView。这样,当您尝试拖动滚动视图并且您的拖动手势从按钮所在的位置开始时,滚动视图就不会卡住。 stackoverflow.com/a/40740616/1121497
      【解决方案5】:

      此方法不需要任何子类化。您只需将UILongPressGestureRecognizer 添加到视图并将minimumPressDuration 设置为零。然后检查调用手势事件时的状态以查看触摸事件是开始还是结束。

      这是上面示例图片的整个项目代码。

      import UIKit
      class ViewController: UIViewController {
          @IBOutlet weak var myView: UIView!
          override func viewDidLoad() {
              super.viewDidLoad()
              let tap = UILongPressGestureRecognizer(target: self, action: #selector(tapHandler))
              tap.minimumPressDuration = 0
              myView.addGestureRecognizer(tap)
          }
      
          @objc func tapHandler(gesture: UITapGestureRecognizer) {
              
              // there are seven possible events which must be handled
      
              if gesture.state == .began {
                  myView.backgroundColor = UIColor.darkGray
                  return
              }
      
              if gesture.state == .changed {
                  print("very likely, just that the finger wiggled around while the user was holding down the button. generally, just ignore this")
                  return
              }
      
              if gesture.state == .possible || gesture.state == .recognized {
                  print("in almost all cases, simply ignore these two, unless you are creating very unusual custom subclasses")
                  return
              }
      
              // the three remaining states are
              // .cancelled, .failed, and .ended
              // in all three cases, must return to the normal button look:
              myView.backgroundColor = UIColor.lightGray
          }
      }
      

      感谢this answer 的创意。

      【讨论】:

      • 这将阻止父滚动视图滚动
      • 迄今为止最好的答案(就像 Suragch 一样!)
      • 天才!正是我需要的。
      • 所以基本上你使用长按识别器而不是普通的点击识别器来避免意外滚动?
      • 伙计们请注意,您还必须处理 .cancelled.failed
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-01
      • 2014-06-21
      • 1970-01-01
      相关资源
      最近更新 更多