首页 文章

如何向UIView添加触摸事件?

提问于
浏览
261

如何向UIView添加触摸事件?
我尝试:

UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, nextY)] autorelease];
[headerView addTarget:self action:@selector(myEvent:) forControlEvents:UIControlEventTouchDown];
// ERROR MESSAGE: UIView may not respond to '-addTarget:action:forControlEvents:'

我不想创建子类和覆盖

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

13 回答

  • 5

    创建一个手势识别器(子类),它将实现触摸事件,如 touchesBegan . 之后您可以将其添加到视图中 .

    这样你就可以使用组合代替子类化(这是请求) .

  • 17

    在iOS 3.2及更高版本中,您可以使用手势识别器 . 例如,这是您处理点击事件的方式:

    //The setup code (in viewDidLoad in your view controller)
    UITapGestureRecognizer *singleFingerTap = 
      [[UITapGestureRecognizer alloc] initWithTarget:self 
                                              action:@selector(handleSingleTap:)];
    [self.view addGestureRecognizer:singleFingerTap];
    
    //The event handling method
    - (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
    {
      CGPoint location = [recognizer locationInView:[recognizer.view superview]];
    
      //Do stuff here...
    }
    

    还有一堆内置手势 . 查看iOS事件处理的文档和 UIGestureRecognizer . 我在github上也有一堆可能有用的示例代码 .

  • 49

    手势识别器

    当您向视图添加Gesture Recognizer时,可以通知许多常用的触摸事件(或手势) . 默认情况下支持以下手势类型:

    • UITapGestureRecognizer Tap (短暂触摸屏幕一次或多次)

    • UILongPressGestureRecognizer Long touch (长时间触摸屏幕)

    • UIPanGestureRecognizer Pan (在屏幕上移动手指)

    • UISwipeGestureRecognizer Swipe (快速移动手指)

    • UIPinchGestureRecognizer Pinch (将两根手指放在一起或分开 - 通常是放大)

    • UIRotationGestureRecognizer Rotate (沿圆周方向移动两根手指)

    除此之外,您还可以制作自己的自定义手势识别器 .

    在Interface Builder中添加手势

    将手势识别器从对象库拖到视图上 .

    enter image description here

    控制从文档大纲中的手势拖动到View Controller代码,以便制作插座和操作 .

    enter image description here

    这应该默认设置,但也要确保视图的 User Action Enabled 设置为true .

    enter image description here

    以编程方式添加手势

    要以编程方式添加手势,您(1)创建手势识别器,(2)将其添加到视图中,以及(3)创建在识别手势时调用的方法 .

    import UIKit
    class ViewController: UIViewController {
    
        @IBOutlet weak var myView: UIView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // 1. create a gesture recognizer (tap gesture)
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:)))
    
            // 2. add the gesture recognizer to a view
            myView.addGestureRecognizer(tapGesture)
        }
    
        // 3. this method is called when a tap is recognized
        @objc func handleTap(sender: UITapGestureRecognizer) {
            print("tap")
        }
    }
    

    Notes

    • sender 参数是可选的 . 如果您不需要对手势的引用,则可以将其保留 . 但是,如果这样做,请删除操作方法名称后面的 (sender:) .

    • handleTap 方法的命名是任意的 . 使用 action: #selector(someMethodName(sender:)) 将其命名为您想要的任何名称 .

    更多例子

    您可以研究我添加到这些视图中的手势识别器,以了解它们的工作原理 .

    enter image description here

    以下是该项目的代码:

    import UIKit
    class ViewController: UIViewController {
    
        @IBOutlet weak var tapView: UIView!
        @IBOutlet weak var doubleTapView: UIView!
        @IBOutlet weak var longPressView: UIView!
        @IBOutlet weak var panView: UIView!
        @IBOutlet weak var swipeView: UIView!
        @IBOutlet weak var pinchView: UIView!
        @IBOutlet weak var rotateView: UIView!
        @IBOutlet weak var label: UILabel!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // Tap
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap))
            tapView.addGestureRecognizer(tapGesture)
    
            // Double Tap
            let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap))
            doubleTapGesture.numberOfTapsRequired = 2
            doubleTapView.addGestureRecognizer(doubleTapGesture)
    
            // Long Press
            let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(gesture:)))
            longPressView.addGestureRecognizer(longPressGesture)
    
            // Pan
            let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(gesture:)))
            panView.addGestureRecognizer(panGesture)
    
            // Swipe (right and left)
            let swipeRightGesture = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipe(gesture:)))
            let swipeLeftGesture = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipe(gesture:)))
            swipeRightGesture.direction = UISwipeGestureRecognizerDirection.right
            swipeLeftGesture.direction = UISwipeGestureRecognizerDirection.left
            swipeView.addGestureRecognizer(swipeRightGesture)
            swipeView.addGestureRecognizer(swipeLeftGesture)
    
            // Pinch
            let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch(gesture:)))
            pinchView.addGestureRecognizer(pinchGesture)
    
            // Rotate
            let rotateGesture = UIRotationGestureRecognizer(target: self, action: #selector(handleRotate(gesture:)))
            rotateView.addGestureRecognizer(rotateGesture)
    
        }
    
        // Tap action
        @objc func handleTap() {
            label.text = "Tap recognized"
    
            // example task: change background color
            if tapView.backgroundColor == UIColor.blue {
                tapView.backgroundColor = UIColor.red
            } else {
                tapView.backgroundColor = UIColor.blue
            }
    
        }
    
        // Double tap action
        @objc func handleDoubleTap() {
            label.text = "Double tap recognized"
    
            // example task: change background color
            if doubleTapView.backgroundColor == UIColor.yellow {
                doubleTapView.backgroundColor = UIColor.green
            } else {
                doubleTapView.backgroundColor = UIColor.yellow
            }
        }
    
        // Long press action
        @objc func handleLongPress(gesture: UILongPressGestureRecognizer) {
            label.text = "Long press recognized"
    
            // example task: show an alert
            if gesture.state == UIGestureRecognizerState.began {
                let alert = UIAlertController(title: "Long Press", message: "Can I help you?", preferredStyle: UIAlertControllerStyle.alert)
                alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
                self.present(alert, animated: true, completion: nil)
            }
        }
    
        // Pan action
        @objc func handlePan(gesture: UIPanGestureRecognizer) {
            label.text = "Pan recognized"
    
            // example task: drag view
            let location = gesture.location(in: view) // root view
            panView.center = location
        }
    
        // Swipe action
        @objc func handleSwipe(gesture: UISwipeGestureRecognizer) {
            label.text = "Swipe recognized"
    
            // example task: animate view off screen
            let originalLocation = swipeView.center
            if gesture.direction == UISwipeGestureRecognizerDirection.right {
                UIView.animate(withDuration: 0.5, animations: {
                    self.swipeView.center.x += self.view.bounds.width
                }, completion: { (value: Bool) in
                    self.swipeView.center = originalLocation
                })
            } else if gesture.direction == UISwipeGestureRecognizerDirection.left {
                UIView.animate(withDuration: 0.5, animations: {
                    self.swipeView.center.x -= self.view.bounds.width
                }, completion: { (value: Bool) in
                    self.swipeView.center = originalLocation
                })
            }
        }
    
        // Pinch action
        @objc func handlePinch(gesture: UIPinchGestureRecognizer) {
            label.text = "Pinch recognized"
    
            if gesture.state == UIGestureRecognizerState.changed {
                let transform = CGAffineTransform(scaleX: gesture.scale, y: gesture.scale)
                pinchView.transform = transform
            }
        }
    
        // Rotate action
        @objc func handleRotate(gesture: UIRotationGestureRecognizer) {
            label.text = "Rotate recognized"
    
            if gesture.state == UIGestureRecognizerState.changed {
                let transform = CGAffineTransform(rotationAngle: gesture.rotation)
                rotateView.transform = transform
            }
        }
    }
    

    Notes

    • 您可以向单个视图添加多个手势识别器 . 但是为了简单起见,我没有这样做(滑动手势除外) . 如果您需要为您的项目,您应该阅读gesture recognizer documentation . 这是相当容易理解和有帮助的 .

    • 上述示例的已知问题:(1)平移视图在下一个手势事件中重置其帧 . (2)第一次滑动时滑动视图来自错误的方向 . (不过,我的示例中的这些错误不应影响您对手势识别器如何工作的理解 . )

  • 0

    我想你可以简单地使用

    UIControl *headerView = ...
    [headerView addTarget:self action:@selector(myEvent:) forControlEvents:UIControlEventTouchDown];
    

    我的意思是headerView从UIControl扩展 .

  • 0

    基于accepted answer,您可以定义一个宏:

    #define handle_tap(view, delegate, selector) do {\
        view.userInteractionEnabled = YES;\
        [view addGestureRecognizer: [[UITapGestureRecognizer alloc] initWithTarget:delegate action:selector]];\
    } while(0)
    

    这个宏使用ARC,因此没有 release 调用 .

    宏用法示例:

    handle_tap(userpic, self, @selector(onTapUserpic:));
    
  • 5

    Swift 3 & Swift 4

    import UIKit
    
    extension UIView {
      func addTapGesture(tapNumber: Int, target: Any, action: Selector) {
        let tap = UITapGestureRecognizer(target: target, action: action)
        tap.numberOfTapsRequired = tapNumber
        addGestureRecognizer(tap)
        isUserInteractionEnabled = true
      }
    }
    

    Use

    yourView.addTapGesture(tapNumber: 1, target: self, action: #selector(yourMethod))
    
  • 9

    您可以通过在代码中添加Gesture Recogniser来实现此目的 .

    Step 1: ViewController.m:

    // Declare the Gesture.
    UITapGestureRecognizer *gesRecognizer = [[UITapGestureRecognizer alloc] 
                                              initWithTarget:self 
                                              action:@selector(handleTap:)];
    gesRecognizer.delegate = self;
    
    // Add Gesture to your view.
    [yourView addGestureRecognizer:gesRecognizer];
    

    Step 2: ViewController.m:

    // Declare the Gesture Recogniser handler method.
    - (void)handleTap:(UITapGestureRecognizer *)gestureRecognizer{
       NSLog(@"Tapped");
    }
    

    注意:这里你的视图是 @property (strong, nonatomic) IBOutlet UIView *localView;

    EDIT: * localView是Main.storyboard中的白色框,从下面开始

    enter image description here

    enter image description here

  • 110

    这是一个Swift版本:

    // MARK: Gesture Extensions
    extension UIView {
    
        func addTapGesture(#tapNumber: Int, target: AnyObject, action: Selector) {
            let tap = UITapGestureRecognizer (target: target, action: action)
            tap.numberOfTapsRequired = tapNumber
            addGestureRecognizer(tap)
            userInteractionEnabled = true
        }
    
        func addTapGesture(#tapNumber: Int, action: ((UITapGestureRecognizer)->())?) {
            let tap = BlockTap (tapCount: tapNumber, fingerCount: 1, action: action)
            addGestureRecognizer(tap)
            userInteractionEnabled = true
        }
    }
    
  • 550

    斯威夫特3:

    let tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapGestureRecognizer(_:)))
    view.addGestureRecognizer(tapGestureRecognizer)
    
    func handleTapGestureRecognizer(_ gestureRecognizer: UITapGestureRecognizer) {
    
    }
    
  • 0

    Swift 4.2 和Xcode 10中

    使用 UITapGestureRecognizer 添加触摸事件

    //Add tap gesture to your view
    let tap = UITapGestureRecognizer(target: self, action: #selector(handleGesture))
    yourView.addGestureRecognizer(tap)
    
    // GestureRecognizer
    @objc func handleGesture(gesture: UITapGestureRecognizer) -> Void {
    //Write your code here
    }
    

    如果你想使用 SharedClass

    //This is my shared class
    import UIKit
    
    class SharedClass: NSObject {
    
        static let sharedInstance = SharedClass()
    
        //Tap gesture function
        func addTapGesture(view: UIView, target: Any, action: Selector) {
            let tap = UITapGestureRecognizer(target: target, action: action)
            view.addGestureRecognizer(tap)
        }
    }
    

    我的ViewController中有3个视图,名为view1,view2和view3 .

    override func viewDidLoad() {
        super.viewDidLoad()
        //Add gestures to your views
        SharedClass.sharedInstance.addTapGesture(view: view1, target: self, action: #selector(handleGesture))
        SharedClass.sharedInstance.addTapGesture(view: view2, target: self, action: #selector(handleGesture))
        SharedClass.sharedInstance.addTapGesture(view: view3, target: self, action: #selector(handleGesture2))
    
    }
    
    // GestureRecognizer
    @objc func handleGesture(gesture: UITapGestureRecognizer) -> Void {
        print("printed 1&2...")
    }
    // GestureRecognizer
    @objc func handleGesture2(gesture: UITapGestureRecognizer) -> Void {
        print("printed3...")
    }
    
  • 16

    这是ios tapgesture;首先,您需要在操作下面编写以下代码后为GestureRecognizer创建操作,如下所示

    - (IBAction)tapgesture:(id)sender
    
    {
    
    
    [_password resignFirstResponder];
    
    
    [_username resignFirstResponder];
    
    NSLog(@" TapGestureRecognizer  tapped");
    
    }
    
  • 0

    另一种方法是在视图中添加透明按钮

    UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom];
    b.frame = CGRectMake(0, 0, headerView.width, headerView.height);
    [headerView addSubview:b];
    [b addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchDown];
    

    然后,处理点击:

    - (void)buttonClicked:(id)sender
    {}
    
  • 2

    你们为什么不试试SSEventListener

    您不需要创建任何手势识别器,并将您的逻辑与另一种方法分开 . SSEventListener 支持在视图上设置侦听器块以侦听单击手势,双击手势和N-tap手势如果你喜欢,并长按手势 . 设置单击手势监听器就变成了这种方式:

    [view ss_addTapViewEventListener:^(UITapGestureRecognizer *recognizer) { ... } numberOfTapsRequired:1];

相关问题