J'ai une UIImageView
que je veux pouvoir redimensionner et faire pivoter, etc.
Peut-on ajouter une UIGestureRecognizer
à la UIImageView
?
J'aimerais ajouter un identificateur de rotation et de pincement à une variable UIImageView
qui serait créée à l'exécution.
Comment ajoute-t-on ces identifiants?
Vérifiez que userInteractionEnabled
est YES
sur UIImageView
. Ensuite, vous pouvez ajouter un identificateur de geste.
imageView.userInteractionEnabled = YES;
UIPinchGestureRecognizer *pgr = [[UIPinchGestureRecognizer alloc]
initWithTarget:self action:@selector(handlePinch:)];
pgr.delegate = self;
[imageView addGestureRecognizer:pgr];
[pgr release];
:
:
- (void)handlePinch:(UIPinchGestureRecognizer *)pinchGestureRecognizer
{
//handle pinch...
}
Oui, un identificateur UIGestureRecognizer peut être ajouté à un UIImageView. Comme indiqué dans l'autre réponse, il est très important de ne pas oublier d'activer l'interaction de l'utilisateur sur la vue d'image en définissant sa propriété userInteractionEnabled
sur YES
. UIImageView hérite de UIView, dont la propriété d'interaction utilisateur est définie sur YES
par défaut. Cependant, la propriété d'interaction utilisateur de UIImageView est définie sur NO
par défaut.
À partir de de la documentation UIImageView:
Les nouveaux objets de vue d'image sont configurés pour ignorer les événements utilisateur par défaut. Si vous souhaitez gérer des événements dans une sous-classe personnalisée de UIImageView, vous devez explicitement modifier la valeur du fichier propriété userInteractionEnabled sur YES après l’initialisation de l’objet.
Quoi qu'il en soit, sur l'essentiel de la réponse. Voici un exemple de création d'une UIImageView
avec une UIPinchGestureRecognizer
, une UIRotationGestureRecognizer
et une UIPanGestureRecognizer
.
Tout d'abord, dans viewDidLoad
, ou une autre méthode de votre choix, créez une vue d'image, donnez-lui une image, un cadre et activez son interaction avec l'utilisateur. Créez ensuite les trois gestes comme suit. Veillez à utiliser leur propriété de délégué (probablement définie sur self). Cela sera nécessaire pour utiliser plusieurs gestes en même temps.
- (void)viewDidLoad
{
[super viewDidLoad];
// set up the image view
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"someImage"]];
[imageView setBounds:CGRectMake(0.0, 0.0, 120.0, 120.0)];
[imageView setCenter:self.view.center];
[imageView setUserInteractionEnabled:YES]; // <--- This is very important
// create and configure the pinch gesture
UIPinchGestureRecognizer *pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchGestureDetected:)];
[pinchGestureRecognizer setDelegate:self];
[imageView addGestureRecognizer:pinchGestureRecognizer];
// create and configure the rotation gesture
UIRotationGestureRecognizer *rotationGestureRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotationGestureDetected:)];
[rotationGestureRecognizer setDelegate:self];
[imageView addGestureRecognizer:rotationGestureRecognizer];
// creat and configure the pan gesture
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureDetected:)];
[panGestureRecognizer setDelegate:self];
[imageView addGestureRecognizer:panGestureRecognizer];
[self.view addSubview:imageView]; // add the image view as a subview of the view controllers view
}
Voici les trois méthodes qui seront appelées lorsque les gestes de votre vue sont détectés. À l'intérieur, nous vérifierons l'état actuel du geste et, s'il est soit dans la variable commencée ou modifiée UIGestureRecognizerState
, nous lirons la propriété scale/rotation/translation du geste, appliquerons ces données à une transformation affine, appliquerons la transformation affine au image, puis réinitialisez les gestes échelle/rotation/translation.
- (void)pinchGestureDetected:(UIPinchGestureRecognizer *)recognizer
{
UIGestureRecognizerState state = [recognizer state];
if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged)
{
CGFloat scale = [recognizer scale];
[recognizer.view setTransform:CGAffineTransformScale(recognizer.view.transform, scale, scale)];
[recognizer setScale:1.0];
}
}
- (void)rotationGestureDetected:(UIRotationGestureRecognizer *)recognizer
{
UIGestureRecognizerState state = [recognizer state];
if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged)
{
CGFloat rotation = [recognizer rotation];
[recognizer.view setTransform:CGAffineTransformRotate(recognizer.view.transform, rotation)];
[recognizer setRotation:0];
}
}
- (void)panGestureDetected:(UIPanGestureRecognizer *)recognizer
{
UIGestureRecognizerState state = [recognizer state];
if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged)
{
CGPoint translation = [recognizer translationInView:recognizer.view];
[recognizer.view setTransform:CGAffineTransformTranslate(recognizer.view.transform, translation.x, translation.y)];
[recognizer setTranslation:CGPointZero inView:recognizer.view];
}
}
Enfin et surtout, vous devrez utiliser la méthode UIGestureRecognizerDelegate method gestureRecognizer: shouldRecognizeSimultaneouslyWithGestureRecognizer
pour permettre aux gestes de fonctionner en même temps. Si ces trois gestes sont les trois seuls gestes auxquels cette classe est attribuée, vous pouvez simplement renvoyer YES
comme indiqué ci-dessous. Toutefois, si vous avez délégué d'autres gestes pour lesquels cette classe est affectée, vous devrez peut-être ajouter une logique à cette méthode pour déterminer quel geste est lequel avant de les autoriser à travailler ensemble.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
N'oubliez pas de vous assurer que votre classe est conforme au protocole UIGestureRecognizerDelegate . Pour ce faire, assurez-vous que votre interface ressemble à ceci:
@interface MyClass : MySuperClass <UIGestureRecognizerDelegate>
Si vous préférez jouer vous-même avec le code dans un exemple de projet, vous trouverez ici l'exemple de projet que j'ai créé et contenant ce code .
Vous créez un identificateur de geste de type tapotement, pincement ou balayage dans le même manoir. Ci-dessous, je vais vous guider à travers 4 étapes pour obtenir votre identificateur opérationnel.
4 étapes
1.) Héritez de UIGestureRecognizerDelegate
en l'ajoutant à votre signature de classe.
class ViewController: UIViewController, UIGestureRecognizerDelegate {...}
2.) Faites glisser le curseur de votre image vers votre viewController pour créer un IBOutlet:
@IBOutlet weak var tapView: UIImageView!
3.) Dans votre viewDidLoad, ajoutez le code suivant:
// create an instance of UITapGestureRecognizer and tell it to run
// an action we'll call "handleTap:"
let tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
// we use our delegate
tap.delegate = self
// allow for user interaction
tapView.userInteractionEnabled = true
// add tap as a gestureRecognizer to tapView
tapView.addGestureRecognizer(tap)
4.) Créez la fonction qui sera appelée lorsque vous appuierez sur votre reconnaissance de geste. (Vous pouvez exclure le = nil
si vous le souhaitez).
func handleTap(sender: UITapGestureRecognizer? = nil) {
// just creating an alert to prove our tap worked!
let tapAlert = UIAlertController(title: "hmmm...", message: "this actually worked?", preferredStyle: UIAlertControllerStyle.Alert)
tapAlert.addAction(UIAlertAction(title: "OK", style: .Destructive, handler: nil))
self.presentViewController(tapAlert, animated: true, completion: nil)
}
Votre code final devrait ressembler à ceci:
class ViewController: UIViewController, UIGestureRecognizerDelegate {
@IBOutlet weak var tapView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
tap.delegate = self
tapView.userInteractionEnabled = true
tapView.addGestureRecognizer(tap)
}
func handleTap(sender: UITapGestureRecognizer? = nil) {
let tapAlert = UIAlertController(title: "hmmm...", message: "this actually worked?", preferredStyle: UIAlertControllerStyle.Alert)
tapAlert.addAction(UIAlertAction(title: "OK", style: .Destructive, handler: nil))
self.presentViewController(tapAlert, animated: true, completion: nil)
}
}
myImageView.isUserInteractionEnabled = true
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped))
tapGestureRecognizer.numberOfTapsRequired = 1
myImageView.addGestureRecognizer(tapGestureRecognizer)
et lorsque vous appuyez sur:
@objc func imageTapped(_ sender: UITapGestureRecognizer) {
// do something when image tapped
print("image tapped")
}
Exemple de Swift 3
override func viewDidLoad() {
self.backgroundImageView.addGestureRecognizer(
UITapGestureRecognizer.init(target: self, action:
#selector(didTapImageview(_:))
)
)
self.backgroundImageView.isUserInteractionEnabled = true
}
func didTapImageview(_ sender: Any) {
// do something
}
}
Aucun délégué d'enregistrement de geste ni autre implémentation si nécessaire.
Je viens de faire cela avec Swift4 en ajoutant 3 gestes ensemble en vue unique
Voici mon exemple de code
class ViewController: UIViewController: UIGestureRecognizerDelegate{
//your image view that outlet from storyboard or xibs file.
@IBOutlet weak var imgView: UIImageView!
// declare gesture recognizer
var panRecognizer: UIPanGestureRecognizer?
var pinchRecognizer: UIPinchGestureRecognizer?
var rotateRecognizer: UIRotationGestureRecognizer?
override func viewDidLoad() {
super.viewDidLoad()
// Create gesture with target self(viewcontroller) and handler function.
self.panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(recognizer:)))
self.pinchRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(self.handlePinch(recognizer:)))
self.rotateRecognizer = UIRotationGestureRecognizer(target: self, action: #selector(self.handleRotate(recognizer:)))
//delegate gesture with UIGestureRecognizerDelegate
pinchRecognizer?.delegate = self
rotateRecognizer?.delegate = self
panRecognizer?.delegate = self
// than add gesture to imgView
self.imgView.addGestureRecognizer(panRecognizer!)
self.imgView.addGestureRecognizer(pinchRecognizer!)
self.imgView.addGestureRecognizer(rotateRecognizer!)
}
// handle UIPanGestureRecognizer
@objc func handlePan(recognizer: UIPanGestureRecognizer) {
let gview = recognizer.view
if recognizer.state == .began || recognizer.state == .changed {
let translation = recognizer.translation(in: gview?.superview)
gview?.center = CGPoint(x: (gview?.center.x)! + translation.x, y: (gview?.center.y)! + translation.y)
recognizer.setTranslation(CGPoint.zero, in: gview?.superview)
}
}
// handle UIPinchGestureRecognizer
@objc func handlePinch(recognizer: UIPinchGestureRecognizer) {
if recognizer.state == .began || recognizer.state == .changed {
recognizer.view?.transform = (recognizer.view?.transform.scaledBy(x: recognizer.scale, y: recognizer.scale))!
recognizer.scale = 1.0
}
}
// handle UIRotationGestureRecognizer
@objc func handleRotate(recognizer: UIRotationGestureRecognizer) {
if recognizer.state == .began || recognizer.state == .changed {
recognizer.view?.transform = (recognizer.view?.transform.rotated(by: recognizer.rotation))!
recognizer.rotation = 0.0
}
}
// mark sure you override this function to make gestures work together
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}
N'importe quelle question, tapez juste pour commenter. Je vous remercie
Vous pouvez également faire glisser un identificateur de gestes tactiles vers la vue de l'image dans Storyboard. Ensuite, créez une action par Ctrl + glisser sur le code ...
Pour les amoureux des blocs, vous pouvez utiliser ALActionBlocks pour ajouter une action de gestes en bloc
__weak ALViewController *wSelf = self;
imageView.userInteractionEnabled = YES;
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithBlock:^(UITapGestureRecognizer *weakGR) {
NSLog(@"pan %@", NSStringFromCGPoint([weakGR locationInView:wSelf.view]));
}];
[self.imageView addGestureRecognizer:gr];