Cách thêm sự kiện chạm vào UIView?


237

Làm cách nào để thêm sự kiện chạm vào UIView?
tôi cố gắng:

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:' 

Tôi không muốn tạo một lớp con và ghi đè lên

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

Đối nhanh chóng bạn có thể lấy nó từ đây: https://stackoverflow.com/questions/28675209/how-to-call-gesture-tap-on -uiview-programmatically-in-swift 07 mar. 182018-03-07 13:45:06

521

Trong iOS 3.2 trở lên, bạn có thể sử dụng recognizers cử chỉ. Ví dụ: đây là cách bạn sẽ xử lý sự kiện nhấn:

//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... 
} 

Có một loạt các cử chỉ được tạo sẵn. Xem tài liệu về xử lý sự kiện trên iOS và UIGestureRecognizer. Tôi cũng có một loạt mã mẫu lên trên github có thể hữu ích.

  0

Nhưng đó là ghi đè hành động defautlt chạm của chế độ xem. ¿Có thể gọi hành động chạm mặc định của chế độ xem không? Một cái gì đó như [super touchesBegan]? ... 13 jul. 112011-07-13 15:53:35

+2

Dòng CGPoint làm gì? 13 may. 122012-05-13 02:11:59

+2

@yourfriendzak 'CGPoint' đại diện cho vị trí của vòi nước trong phần giám sát của chế độ xem được khai thác. Bạn có thể sử dụng điểm này để di chuyển chế độ xem được khai thác (hoặc chế độ xem anh chị em) đến vị trí được khai thác. Điều này hữu ích hơn trong trình xử lý cho 'UIPanGestureRecognizer' để kéo chế độ xem xung quanh màn hình. 15 may. 122012-05-15 17:10:02

+5

câu trả lời ngắn gọn tuyệt vời, cảm ơn. nhưng sheesh, nó sẽ không được tốt đẹp nếu điều này là một chút wee dễ dàng hơn ?! :) 20 may. 122012-05-20 22:56:50

  0

Nó không phải là quá xấu, nhưng tôi muốn có một khối dựa trên API như https://github.com/neror/ftutils/blob/master/Headers/FTUtils/FTUtils%2BUIGestureRecognizer.h. Xcode 4 cũng hỗ trợ thêm/định cấu hình trình nhận dạng cử chỉ trong Trình tạo giao diện. 24 may. 122012-05-24 16:03:42

  0

Tôi nhận được hầu hết điều này để làm việc; tuy nhiên, tại sao khi tôi in tọa độ bằng cách sử dụng NSLog (@ "điểm chạm:% f,% f", location.x, location.y); tôi luôn nhận được 0.00000, 0.00000 ??? có phải vì giả lập của tôi không? Tôi đang sử dụng trackpad của mình trên mac pro 08 aug. 122012-08-08 05:20:02

  0

@NathanEror UIView chỉ có thể thêm MỘT GestureRecognizer. Tôi cố gắng xử lý nhiều hơn một EventHandler. https://gist.github.com/1450404 07 sep. 122012-09-07 06:38:25

  0

bạn phải thêm view.userInteractionEnabled = YES; 10 mar. 162016-03-10 14:14:14

  0

Có sự khác biệt giữa một lần chạm và một sự kiện chạm, với nhiều con trỏ và trạng thái xuống/di chuyển/lên. Hầu như mỗi câu trả lời đều nói về một lần chạm ... 07 aug. 172017-08-07 20:27:43


50

Tôi nghĩ rằng bạn chỉ có thể sử dụng

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

tôi có nghĩa là headerView kéo dài từ UIControl.

+6

Đây là câu trả lời hay hơn. 'UITapGestureRecognizer' không thay thế' UIControlEventTouchDown'. Một 'Tap' thường bao gồm' UIControlEventTouchDown' và 'UIControlEventTouchUpInside'. 31 oct. 122012-10-31 02:42:19

+60

Một 'UIView' không phải là một' UIControl' và do đó không có quyền truy cập vào 'addTarget: action: forControlEvents:'. 21 nov. 122012-11-21 22:32:40

+8

Cũng lưu ý rằng một UIControl kế thừa từ UIView. Vì mục đích của tôi, tất cả những gì tôi phải làm là một chuyển đổi đơn giản của kiểu lớp con. 14 feb. 132013-02-14 04:29:27

+1

bạn có thể đặt lớp của nó thành UIControl @RobertJoseph .. Vào tệp xib và đặt lớp View Custom thành UIControl. bây giờ bạn có thể xử lý sự kiện trong đó .. 05 sep. 142014-09-05 11:22:56

+2

Vậy tại sao lại là giải pháp tốt hơn này vì tôi đang thay đổi kế thừa chỉ để xử lý các thao tác nhấn? 12 nov. 142014-11-12 19:23:34


16

Dựa trên accepted answer bạn có thể định nghĩa một macro:

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

vĩ mô này sử dụng ARC, vì vậy không có release gọi.

sử dụng Macro dụ:

handle_tap(userpic, self, @selector(onTapUserpic:)); 
+4

Nếu bạn tạo chế độ xem trong bảng phân cảnh, đừng quên bật tùy chọn "tương tác với người dùng đã bật". 25 sep. 132013-09-25 08:23:46

  0

nơi chúng ta nên xác định macro trong .h hoặc .m và tên của các tham số là gì. tôi có nghĩa là #define handle_tap (UIView xem, đại biểu ủy nhiệm, SEL selector) làm .. 05 sep. 142014-09-05 11:54:29

  0

sooo thuận tiện là sooo nhiều cách, cảm ơn bạn !! A +++ 04 dec. 162016-12-04 10:48:06

  0

Gia hạn http://hypple.co 30 may. 172017-05-30 10:13:52


9

Bạn có thể đạt được điều này bằng cách thêm Gesture Recogniser trong mã của bạn.

Bước 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]; 

Bước 2: ViewController.m:

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

LƯU Ý: đây yourView trong trường hợp của tôi là @property (strong, nonatomic) IBOutlet UIView *localView;

EDIT: * localView là hộp màu trắng i n Main.storyboard từ bên dưới

enter image description here

enter image description here

  0

tôi đang có nhiều chế độ xem để tôi có thể gửi id người gửi? 06 jan. 162016-01-06 04:11:37

  0

Bạn phải đi đến subview bên trong, sau đó bạn có thể paas người gửi. - cho (UIView * xem trong self.topicScrollView.subviews) {// Go Inside the superview if ([view isKindOfClass: [UIButton class]]) {// Chuyển đến chế độ xem cụ thể đó // Tại đây bạn đã đạt đến điểm đó. } } 06 jan. 162016-01-06 09:27:08


5

Heres một phiên bản 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 
    } 
} 
  0

'BlockTap' là gì? 30 aug. 162016-08-30 13:41:34

+1

Ôi trời, quên phần đó. Chức năng tùy chỉnh của nó. Tại đây: https://github.com/goktugyil/EZSwiftExtensions/blob/master/Sources/BlockTap.swift 30 aug. 162016-08-30 15:57:55


79

Gesture Recognizers

Có một số thường được sử dụng sự kiện liên lạc (hoặc cử chỉ) bạn có thể được thông báo khi thêm Gesture Recognizer vào chế độ xem của mình.Họ sau loại cử chỉ được hỗ trợ theo mặc định:

  • UITapGestureRecognizerTap (chạm vào màn hình một thời gian ngắn một hoặc nhiều lần)
  • UILongPressGestureRecognizerChạm và giữ (chạm vào màn hình trong một thời gian dài)
  • UIPanGestureRecognizerPan (di chuyển ngón tay trên màn hình)
  • UISwipeGestureRecognizerVuốt (di chuyển ngón tay một cách nhanh chóng)
  • UIPinchGestureRecognizerPinch (di chuyển hai ngón tay lại với nhau hoặc cách nhau - thường để phóng to)
  • UIRotationGestureRecognizerXoay (di chuyển hai ngón tay theo một hướng hình tròn)

Ngoài bạn cũng có thể tạo trình nhận dạng cử chỉ tùy chỉnh của riêng mình.

Thêm một cử chỉ trong giao diện Builder

Kéo một trình nhận dạng cử chỉ từ thư viện đối tượng vào tầm nhìn của bạn.

enter image description here

kiểm soát kéo từ cử chỉ trong Outline Document mã View Controller của bạn để làm cho một Outlet và một hành động.

enter image description here

Thêm một cử chỉ lập trình

Để thêm một cử chỉ lập trình, bạn (1) tạo ra một nhận dạng cử chỉ, (2) thêm nó vào một cái nhìn, và (3) tạo ra một phương pháp đó là được gọi khi cử chỉ được nhận ra.

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 
    func handleTap(sender: UITapGestureRecognizer) { 
     print("tap") 
    } 
} 

Ghi chú

  • Tham số sender là không bắt buộc. Nếu bạn không cần tham chiếu đến cử chỉ thì bạn có thể bỏ nó ra. Nếu bạn làm như vậy, hãy xóa (_:) sau tên phương thức hành động khi tạo cử chỉ.
  • Cách đặt tên của phương pháp handleTap là tùy ý. Đặt tên nó là bất cứ điều gì bạn muốn sử dụng action: #selector(someMethodName(sender:)).

More Ví dụ

Bạn có thể nghiên cứu bên nhận cử chỉ mà tôi thêm vào những quan điểm để xem cách họ làm việc.

enter image description here

Đây là mã cho dự án:

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 
    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 
    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 
    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 
    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 
    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 
    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 
    func handleRotate(gesture: UIRotationGestureRecognizer) { 
     label.text = "Rotate recognized" 

     if gesture.state == UIGestureRecognizerState.changed { 
      let transform = CGAffineTransform(rotationAngle: gesture.rotation) 
      rotateView.transform = transform 
     } 
    } 
} 

Ghi chú

  • Bạn có thể thêm nhiều recognizers cử chỉ để một cái nhìn duy nhất. Vì lợi ích của sự đơn giản, mặc dù, tôi đã không làm điều đó (ngoại trừ cử chỉ vuốt). Nếu bạn cần cho dự án của bạn, bạn nên đọc gesture recognizer documentation. Nó khá dễ hiểu và hữu ích.
  • Sự cố đã biết với ví dụ của tôi ở trên: (1) Chế độ xem xoay đặt lại khung của nó trên sự kiện cử chỉ tiếp theo. (2) Chế độ xem vuốt đến từ hướng sai trên lần vuốt đầu tiên. (. Những lỗi trong ví dụ của tôi không ảnh hưởng đến sự hiểu biết của bạn về cách Gestures Recognizers làm việc, mặc dù)

Cập nhật cho Swift 3

+1

Câu trả lời của bạn thật sự rất hay và hữu ích với mô tả chi tiết. Và đó là lý do tại sao tôi đã bỏ phiếu bạn cũng trả lời. Nhưng bạn chỉ cần bỏ lỡ một hướng dẫn mà tôi nghĩ rằng bạn phải bao gồm trong câu trả lời của bạn như bạn đã giải thích nó đầy đủ chi tiết. Hướng dẫn đó là về việc đặt "<yourView> .EnableUserInteraction = TRUE". Tôi hy vọng bạn đồng ý với tôi. 22 mar. 172017-03-22 05:53:25

  0

@ Er.Vihar: Đó là một điểm tốt. Tôi sẽ thêm câu trả lời này vào danh sách những thứ cần cập nhật. Cho đến lúc đó, những người dùng khác có thể lưu ý nhận xét của bạn. 22 mar. 172017-03-22 06:20:08

  0

Tài liệu tuyệt vời! 19 jan. 182018-01-19 23:36:33


0

Đây là ios tapgesture; Trước tiên, bạn cần phải tạo ra hành động cho GestureRecognizer sau khi viết mã dưới đây dưới tác động như hình dưới đây

- (IBAction)tapgesture:(id)sender 

{ 


[_password resignFirstResponder]; 


[_username resignFirstResponder]; 

NSLog(@" TapGestureRecognizer tapped"); 

} 

0

Một cách khác là thêm một nút trong suốt đối với quan điểm

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

Và sau đó, xử lý click:

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

4

Swift 3 cập nhật

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 

    } 
} 

Sử dụng

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

0

Tạo một trình nhận dạng cử chỉ (lớp con), mà sẽ triển khai sự kiện liên lạc, như touchesBegan. Bạn có thể thêm nó vào chế độ xem sau đó.

Bằng cách này, bạn sẽ sử dụng bố cục thay vì phân lớp (là yêu cầu).


4

Swift 3:

let tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapGestureRecognizer(_:))) 
view.addGestureRecognizer(tapGestureRecognizer) 

func handleTapGestureRecognizer(_ gestureRecognizer: UITapGestureRecognizer) { 

} 

0

Tại sao bạn không thử kẻ SSEventListener?

Bạn không cần tạo bất kỳ trình nhận dạng cử chỉ nào và tách biệt logic của bạn với một phương pháp khác. SSEventListener hỗ trợ cài đặt khối người nghe trên một chế độ xem để nghe cử chỉ chạm một lần, nhấn đúp cử chỉ và cử chỉ N-tap nếu bạn thích và cử chỉ báo chí dài. Thiết lập một listener tap cử chỉ đơn trở thành theo cách này:

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