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
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.
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.
Faites glisser un identificateur de mouvements de la bibliothèque d'objets sur votre vue.
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.
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.
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
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.handleTap
était arbitraire. Nommez-le comme vous voulez en utilisant action: #selector(someMethodName(sender:))
.Vous pouvez étudier les outils de reconnaissance de geste que j'ai ajoutés à ces vues pour voir comment ils fonctionnent.
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
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.
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:));
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))
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
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...")
}
Swift 3:
let tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapGestureRecognizer(_:)))
view.addGestureRecognizer(tapGestureRecognizer)
func handleTapGestureRecognizer(_ gestureRecognizer: UITapGestureRecognizer) {
}
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
}
}
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");
}
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
{}
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).
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];