Comment ajouter un événement tactile à un UIView?


237

Comment ajouter un événement tactile à un UIView?
J'essaie:

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

Je ne veux pas créer une sous-classe et écraser

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

Pour rapidement vous pouvez l'obtenir à partir d'ici: https://stackoverflow.com/questions/28675209/how-to-call-gesture-tap-on -uiview-programatically-in-swift 07 mars. 182018-03-07 13:45:06

521

Dans iOS 3.2 et plus, vous pouvez utiliser le geste de reconnaissance. Par exemple, voici comment vous gérez un événement du robinet:

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

Il y a un tas de construire dans des gestes aussi. Consultez les docs pour la gestion des événements iOS et UIGestureRecognizer. J'ai aussi un tas d'exemples de code sur github qui pourrait aider.

  0

Mais c'est l'écrasement de l'action defautlt de la vue. ¿Est-il possible d'appeler l'action tactile par défaut de la vue? Quelque chose comme [super touchesBegan]? ... 13 juil.. 112011-07-13 15:53:35

+2

Que fait la ligne CGPoint? 13 mai. 122012-05-13 02:11:59

+2

@yourfriendzak 'CGPoint' représente l'emplacement du tap dans la vue principale de la vue tapée. Vous pouvez utiliser ce point pour déplacer l'affichage tapé (ou une vue de frère) vers l'emplacement sélectionné. Ceci est plus utile dans le gestionnaire pour un 'UIPanGestureRecognizer' pour faire glisser la vue autour de l'écran. 15 mai. 122012-05-15 17:10:02

+5

grande réponse concise, merci. mais sheesh, ne serait-ce pas bien si c'était un peu plus facile ?! :) 20 mai. 122012-05-20 22:56:50

  0

Ce n'est pas si mal, mais j'aimerais qu'il y ait une API basée sur un bloc comme https://github.com/neror/ftutils/blob/master/Headers/FTUtils/FTUtils%2BUIGestureRecognizer.h. Xcode 4 prend également en charge l'ajout/la configuration de reconnaissance de gestes dans Interface Builder. 24 mai. 122012-05-24 16:03:42

  0

J'ai obtenu la plupart de ceci au travail; cependant, pourquoi est-ce que lorsque j'imprime les coordonnées en utilisant NSLog (@ "points touchés:% f,% f", location.x, location.y); je reçois toujours 0.00000, 0.00000 ??? est-ce à cause de mon simulateur? J'utilise mon trackpad sur mon mac pro 08 août. 122012-08-08 05:20:02

  0

@NathanEror UIView peut seulement ajouter ONE GestureRecognizer. J'essaie de gérer plus d'un EventHandler. https://gist.github.com/1450404 07 sept.. 122012-09-07 06:38:25

  0

vous devez ajouter view.userInteractionEnabled = YES; 10 mars. 162016-03-10 14:14:14

  0

Il existe une différence entre un seul tap et un événement tactile, avec plusieurs pointeurs et des états bas/haut/haut. Presque chacune des réponses parle d'un seul robinet ... 07 août. 172017-08-07 20:27:43


50

Je pense que vous pouvez simplement utiliser

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

je veux dire headerView va de UIControl.

+6

C'est la meilleure réponse. 'UITapGestureRecognizer' n'est pas un remplacement de' UIControlEventTouchDown'. Un 'Tap' compose habituellement de' UIControlEventTouchDown' et 'UIControlEventTouchUpInside'. 31 oct.. 122012-10-31 02:42:19

+60

Un 'UIView' n'est pas un' UIControl' et n'a donc pas accès à 'addTarget: action: forControlEvents:'. 21 nov.. 122012-11-21 22:32:40

+8

Notez également qu'un UIControl hérite de UIView. Pour mes besoins, tout ce que j'avais à faire était un simple changement de type de sous-classe. 14 févr.. 132013-02-14 04:29:27

+1

vous pouvez définir sa classe sur UIControl @RobertJoseph. Accédez au fichier xib et définissez la classe View Custom sur UIControl. Maintenant, vous pouvez gérer l'événement en elle .. 05 sept.. 142014-09-05 11:22:56

+2

Alors pourquoi est-ce une meilleure solution à nouveau puisque je change d'héritage juste pour gérer les robinets? 12 nov.. 142014-11-12 19:23:34


16

Basé sur le accepted answer vous pouvez définir une macro:

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

Cette macro utilise ARC, donc il n'y a pas d'appel release.

Exemple d'utilisation Macro:

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

Si vous créez la vue dans le storyboard, n'oubliez pas d'activer l'option "interaction utilisateur activée". 25 sept.. 132013-09-25 08:23:46

  0

où nous devrions définir des macros en .h ou .m et quel devrait être le nom des paramètres. je veux dire #define handle_tap (vue UIView, délégué délégué, sélecteur SEL) do .. 05 sept.. 142014-09-05 11:54:29

  0

sooo pratique est tellement de façons, merci !! A +++ 04 déc.. 162016-12-04 10:48:06

  0

Renouveler http://hypple.co 30 mai. 172017-05-30 10:13:52


9

Vous pouvez y parvenir en ajoutant Recogniser Gesture dans votre code.

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

Étape 2: ViewController.m:

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

NOTE: ici yourView dans mon cas était @property (strong, nonatomic) IBOutlet UIView *localView;

EDIT: * localView est la boîte blanche i n Main.storyboard en bas

enter image description here

enter image description here

  0

J'ai plusieurs vues, puis-je pouvoir l'ID de l'expéditeur ?? 06 janv.. 162016-01-06 04:11:37

  0

Vous devez aller à la sous-vue intérieure, alors vous pouvez paas l'expéditeur .--------- pour (vue UIView * dans self.topicScrollView.subviews) {// Aller à l'intérieur de la vue d'ensemble if ([voir isKindOfClass: [classe UIButton]]) {// Aller à cette vue particulière // Ici, vous avez atteint ce point. } } 06 janv.. 162016-01-06 09:27:08


5

Heres une version 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

qu'est-ce que 'BlockTap'? 30 août. 162016-08-30 13:41:34

+1

Oh mec, j'ai oublié cette partie. C'est une fonction personnalisée. Ici: https://github.com/goktugyil/EZSwiftExtensions/blob/master/Sources/BlockTap.swift 30 août. 162016-08-30 15:57:55


79

Gesture Recognizers

Il y a un certain nombre d'événements tactiles couramment utilisés (ou gestes) que vous pouvez être averti lorsque vous ajoutez un Gesture Recognizer à votre affichage.Ils suivant les types de geste sont pris en charge par défaut:

  • UITapGestureRecognizerTap (toucher l'écran brièvement une ou plusieurs fois)
  • UILongPressGestureRecognizertouche longue (touchant l'écran pendant une longue période)
  • UIPanGestureRecognizerPanoramique (déplacement de votre doigt sur l'écran)
  • UISwipeGestureRecognizerBalayez (doigt se déplaçant rapidement)
  • UIPinchGestureRecognizerPincez (se déplaçant deux doigts ensemble ou séparément - habituellement pour agrandir)
  • UIRotationGestureRecognizerRotation (se déplaçant deux doigts dans une direction circulaire)

Outre ceux-ci, vous pouvez également faire votre propre reconnaisseur de geste personnalisé.

Ajout d'un Gesture dans l'interface Builder

Faites glisser un geste de reconnaissance de la bibliothèque d'objets sur votre point de vue.

enter image description here

glisser le contrôle du geste dans le plan du document à la vue du code contrôleur afin de faire une sortie et une action.

enter image description here

Ajout d'un Gesture Programmatically

Pour ajouter un geste programme, vous (1) créer un module de reconnaissance de geste, (2) l'ajouter à une vue, et (3) faire une méthode qui est appelé lorsque le geste est reconnu.

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

Remarques

  • Le paramètre sender est en option. Si vous n'avez pas besoin d'une référence au geste, vous pouvez le laisser de côté. Si vous le faites, supprimez le (_:) après le nom de la méthode d'action lors de la création du mouvement. La dénomination de la méthode handleTap était arbitraire. Nommez-le comme vous voulez en utilisant action: #selector(someMethodName(sender:)).

Autres exemples

Vous pouvez étudier les dispositifs de reconnaissance geste que j'ajouté à ces vues pour voir comment ils fonctionnent.

enter image description here

Voici le code pour ce projet:

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

Remarques

  • Vous pouvez ajouter plusieurs gestes à une vue de reconnaissance unique. Par souci de simplicité, cependant, je n'ai pas fait cela (sauf pour le geste de balayage). Si vous en avez besoin pour votre projet, vous devriez lire le gesture recognizer documentation. C'est assez compréhensible et utile.
  • Problèmes connus avec mes exemples ci-dessus: (1) La vue panoramique réinitialise son image lors de l'événement gestuel suivant. (2) La vue Swipe vient de la mauvaise direction lors du premier balayage. (. Ces bugs dans mes exemples ne devraient pas affecter votre compréhension de la façon dont fonctionne Gestures Recognizers, bien que)

Mise à jour pour Swift 3

+1

Votre réponse est vraiment agréable et utile avec une description détaillée. Et c'est pourquoi j'ai voté, vous répondez aussi. Mais vous avez manqué une instruction que vous devez inclure dans votre réponse, comme vous l'avez expliqué en détail. Cette instruction consiste à définir "<yourView> .EnableUserInteraction = TRUE". J'espère que vous êtes d'accord avec moi. 22 mars. 172017-03-22 05:53:25

  0

@ Er.Vihar: C'est un bon point. Je vais ajouter cette réponse à ma liste de choses à mettre à jour. Jusque-là, les autres utilisateurs peuvent prendre note de votre commentaire. 22 mars. 172017-03-22 06:20:08

  0

Grande documentation! 19 janv.. 182018-01-19 23:36:33


0

Voici ios tapgesture; Tout d'abord, vous devez créer une action pour GestureRecognizer écrire après le code ci-dessous sous l'action comme indiqué ci-dessous

- (IBAction)tapgesture:(id)sender 

{ 


[_password resignFirstResponder]; 


[_username resignFirstResponder]; 

NSLog(@" TapGestureRecognizer tapped"); 

} 

0

Une autre façon est l'ajout d'un bouton transparent à la vue

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

Et puis, poignée cliquez sur:

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

4

Swift 3 Mise à jour

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 

    } 
} 

Utilisez

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

0

Créer un geste de reconnaissance (sous-classe), qui mettra en œuvre les événements tactiles, comme touchesBegan. Vous pouvez l'ajouter à la vue après cela.

De cette façon, vous utiliserez la composition à la place du sous-classement (qui était la demande).


4

Swift 3:

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

func handleTapGestureRecognizer(_ gestureRecognizer: UITapGestureRecognizer) { 

} 

0

Pourquoi les gars vous pas essayer SSEventListener?

Vous n'avez pas besoin de créer de reconnaissance de mouvement et de séparer votre logique d'une autre méthode. SSEventListener prend en charge la définition des blocs de l'écouteur dans une vue pour écouter un seul geste de tapotement, un double geste de tapotement et un geste N-tap si vous le souhaitez, et un appui long. Définition d'un seul écouteur geste du robinet devient ainsi:

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