web-dev-qa-db-fra.com

Comment ajouter un événement tactile à UIView?

Comment ajouter un événement tactile à 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 de sous-classe et écraser

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

Dans iOS 3.2 et versions ultérieures, vous pouvez utiliser des dispositifs de reconnaissance de geste. Par exemple, voici comment vous gérez un événement tap:

//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 aussi un tas de gestes intégrés. Consultez la documentation pour la gestion des événements iOS et UIGestureRecognizer. J'ai aussi un tas d'exemples de code sur github qui pourraient aider.

565
Nathan Eror

Reconnaissance gestuelle

Il existe un certain nombre d'événements tactiles (ou de gestes) couramment utilisés dont vous pouvez être averti lorsque vous ajoutez un Gesture Recognizer à votre vue. Les types de geste suivants sont pris en charge par défaut:

  • UITapGestureRecognizer Tapez sur (en touchant l'écran brièvement une ou plusieurs fois)
  • UILongPressGestureRecognizer Touchez longuement (touchez l'écran pendant longtemps)
  • UIPanGestureRecognizer Pan (déplacez votre doigt sur l'écran)
  • UISwipeGestureRecognizer Balayez (le doigt se déplace rapidement)
  • UIPinchGestureRecognizer Pincez (en rapprochant ou rapprochant deux doigts - généralement pour zoomer)
  • UIRotationGestureRecognizer Tourner (déplacer deux doigts dans une direction circulaire)

En plus de cela, vous pouvez également créer votre propre outil de reconnaissance de geste.

Ajout d'un geste dans l'interface Builder

Faites glisser un identificateur de mouvements de la bibliothèque d'objets sur votre vue.

enter image description here

Contrôlez le glissement du geste dans la structure du document vers le code de votre View Controller afin de créer une prise et une action.

enter image description here

Cela doit être défini par défaut, mais assurez-vous également que Action utilisateur activée est définie sur true pour votre vue.

enter image description here

Ajout d'un geste par programme

Pour ajouter un geste par programme, vous devez (1) créer un identificateur de geste, (2) l'ajouter à une vue et (3) créer une méthode appelée lors de la reconnaissance du geste.

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

  • Le paramètre sender est facultatif. Si vous n'avez pas besoin d'une référence au geste, vous pouvez l'omettre. Si vous le faites cependant, supprimez le (sender:) après le nom de la méthode d'action.
  • La désignation de la méthode handleTap était arbitraire. Nommez-le comme vous voulez en utilisant action: #selector(someMethodName(sender:)).

Plus d'exemples

Vous pouvez étudier les outils de reconnaissance de geste que j'ai ajoutés à 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
    @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

  • Vous pouvez ajouter plusieurs identificateurs de mouvements à une seule vue. Par souci de simplicité, cependant, je ne l'ai pas fait (sauf pour le geste de glisser). Si vous en avez besoin pour votre projet, vous devriez lire le documentation de reconnaissance de mouvements . C'est assez compréhensible et utile.
  • Problèmes connus liés à mes exemples ci-dessus: (1) La vue Panoramique réinitialise son cadre lors de l'événement de geste suivant. (2) La vue par balayage provient de la mauvaise direction lors du premier balayage. (Ces bugs dans mes exemples ne devraient cependant pas affecter votre compréhension du fonctionnement des reconnaissance de gestes.)
115
Suragch

Je pense que vous pouvez simplement utiliser

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

je veux dire headerView s'étend de UIControl.

50
LiCheng

En fonction du réponse acceptée , 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. Il n'y a donc pas d'appel release.

Exemple d'utilisation de la macro:

handle_tap(userpic, self, @selector(onTapUserpic:));
18
rudyryk

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

tiliser

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

Vous pouvez y parvenir en ajoutant Gesture Recogniser 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 votre vue dans mon cas était @property (strong, nonatomic) IBOutlet UIView *localView;

EDIT: * localView est la boîte blanche dans Main.storyboard par le bas

enter image description here

enter image description here

9
Annu

Dans Swift 4.2 et Xcode 10

Utilisez ITapGestureRecognizer pour ajouter un événement tactile

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

Si vous voulez utiliser 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)
    }
} 

J'ai 3 vues dans mon ViewController appelé view1, view2 et 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...")
}
6
iOS

Swift 3:

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

func handleTapGestureRecognizer(_ gestureRecognizer: UITapGestureRecognizer) {

}
5
Giang

Voici 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
    }
}
5
Esqarrouth

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

- (IBAction)tapgesture:(id)sender

{


[_password resignFirstResponder];


[_username resignFirstResponder];

NSLog(@" TapGestureRecognizer  tapped");

}
0
sathish

Une autre façon consiste à ajouter 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, gérez le clic:

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

Créez un identificateur de mouvements (sous-classe), qui implémentera des é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 (ce qui était la demande).

0
Geri

Pourquoi n'essayez-vous pas SSEventListener ?

Vous n'avez pas besoin de créer de reconnaissance de geste et de séparer votre logique en une autre méthode. SSEventListener prend en charge la définition de blocs d'écoute dans une vue pour écouter les gestes simples, les gestes doubles et les tapotements si vous le souhaitez, ainsi que les mouvements prolongés. Définir un écouteur à geste unique devient ainsi:

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

0
Shengsheng