UIGestureRecognizer su UIImageView


179

Ho un UIImageView, che voglio essere in grado di ridimensionare e ruotare ecc.

Può UIGestureRecognizeressere aggiunto a UIImageView?

Vorrei aggiungere un riconoscitore di rotazione e pizzico a un UIImageViewche verrebbe creato in fase di esecuzione.

Come si aggiungono questi riconoscitori?

Risposte:


426

Controlla che userInteractionEnabledsia YESsul UIImageView. Quindi è possibile aggiungere un riconoscimento gesti.

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

5
No, questo mostra solo come aggiungere i riconoscitori di gesti. Devi fare lo zoom reale / ruotare te stesso nei gestori di gesti. Guarda l'app di esempio Touches_GestureRecognizers su come eseguire lo zoom / rotazione.

77
+1 è rimasto qui per anni a cercare di capire perché i miei gesti non funzionavano. "Verifica che userInteractionEnabled sia SÌ su UIImageView." Grazie!
Critter,

1
Ciò ha sicuramente reso il mio lavoro più semplice rispetto al tentativo di impostare limiti su un riconoscitore impostato sulla vista generale. Grazie!
Josh Kovach,

6
imageView.userInteractionEnabled = YES; questa è la chiave! Grazie.
HamasN,

3
userInteractionEnableddeve ancora essere impostato su SÌ / vero in Xcode 8 Objective-C / Swift
leanne

76

Sì, un UIGestureRecognizer può essere aggiunto a UIImageView. Come indicato nell'altra risposta, è molto importante ricordare di abilitare l'interazione dell'utente sulla vista dell'immagine impostando la sua userInteractionEnabledproprietà su YES. UIImageView eredita da UIView, la cui proprietà di interazione dell'utente è impostata di YESdefault, tuttavia, la proprietà di interazione dell'utente di UIImageView è impostata di NOdefault.

Dai documenti UIImageView:

I nuovi oggetti vista immagine sono configurati per ignorare gli eventi utente per impostazione predefinita. Se si desidera gestire gli eventi in una sottoclasse personalizzata di UIImageView, è necessario modificare esplicitamente il valore della proprietà userInteractionEnabled su YES dopo aver inizializzato l'oggetto.

Comunque, sulla maggior parte della risposta. Ecco un esempio di come creare a UIImageViewcon a UIPinchGestureRecognizer, a UIRotationGestureRecognizere a UIPanGestureRecognizer.

Innanzitutto, in viewDidLoado un altro metodo a tua scelta, crea una vista immagine, assegnale un'immagine, una cornice e abilita l'interazione dell'utente. Quindi crea i tre gesti come segue. Assicurati di utilizzare la proprietà del delegato (molto probabilmente impostata su self). Ciò sarà necessario per utilizzare più gesti contemporaneamente.

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

Ecco i tre metodi che verranno chiamati quando vengono rilevati i gesti nella tua vista. Al loro interno, controlleremo lo stato corrente del gesto e, se è nella fase iniziale o modificata UIGestureRecognizerState, leggeremo la proprietà della scala / rotazione / traduzione del gesto, applicheremo quei dati a una trasformazione affine, applicheremo la trasformazione affine all'immagine visualizzare, quindi ripristinare la scala / rotazione / traduzione dei gesti.

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

Infine e, cosa molto importante, dovrai utilizzare il metodo UIGestureRecognizerDelegategestureRecognizer: shouldRecognizeSimultaneouslyWithGestureRecognizer per consentire ai gesti di funzionare contemporaneamente. Se questi tre gesti sono i soli tre gesti a cui questa classe è assegnata come delegato, puoi semplicemente tornare YEScome mostrato di seguito. Tuttavia, se hai gesti aggiuntivi a cui è assegnata questa classe come delegato, potresti dover aggiungere la logica a questo metodo per determinare quale gesto è quale prima di consentire loro di lavorare tutti insieme.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

Non dimenticare di assicurarti che la tua classe sia conforme al protocollo UIGestureRecognizerDelegate . Per fare ciò, assicurati che la tua interfaccia sia simile a questa:

@interface MyClass : MySuperClass <UIGestureRecognizerDelegate>

Se preferisci giocare tu stesso con il codice in un progetto di esempio funzionante, puoi trovare il progetto di esempio che ho creato contenente questo codice qui.


1
Questa è di gran lunga la migliore risposta che io abbia mai visto in stackoverflow.com, dettagliata, ben commentata e include persino il codice sorgente su git. Grazie per quello
Alejandro Luengo

1
Chiaro, passo dopo passo, spiegazione fantastica
Alvin,

1
Grazie, ciò ha fatto in una o due pagine ciò che diverse decine di tutorial nel corso degli anni di Apple e altri non sono riusciti a fare. Sento che ci devono essere molte altre cose possibili in iOS, ma a causa dell'offuscamento e dell'incomprensione ci perdono.
Zack Morris,

Ottima risposta, la migliore. Grazie mille per la tua pazienza.
Jorg B Jorge

13

Rapido 4.2

myImageView.isUserInteractionEnabled = true
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped))
tapGestureRecognizer.numberOfTapsRequired = 1
myImageView.addGestureRecognizer(tapGestureRecognizer)

e quando toccato:

@objc func imageTapped(_ sender: UITapGestureRecognizer) {
   // do something when image tapped
   print("image tapped")
}

11

Soluzione Swift 2.0

Si crea un riconoscimento di gesti di tocco, pizzico o scorrimento nello stesso maniero. Di seguito ti guiderò attraverso 4 passaggi per mettere in funzione il tuo riconoscimento.

4 passaggi

1.) Eredita UIGestureRecognizerDelegateda aggiungendolo alla tua firma di classe.

class ViewController: UIViewController, UIGestureRecognizerDelegate {...}

2.) Controlla il trascinamento dall'immagine al viewController per creare un IBOutlet:

@IBOutlet weak var tapView: UIImageView!

3.) Nel tuo viewDidLoad aggiungi il seguente codice:

// 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.) Creare la funzione che verrà chiamata quando si tocca il riconoscimento dei gesti. (È possibile escludere il = nilse si sceglie).

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

Il tuo codice finale dovrebbe assomigliare a questo:

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


6

L'ho appena fatto con swift4 aggiungendo 3 gesti in un'unica vista

  1. UIPinchGestureRecognizer : ingrandisci e rimpicciolisci la vista.
  2. UIRotationGestureRecognizer : ruota la vista.
  3. UIPanGestureRecognizer : trascinamento della vista.

Ecco il mio codice di esempio

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
     }

}

Qualsiasi domanda, basta digitare per commentare. grazie


3

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

Nessun delegato di ricongiungimento gestuale o altre implementazioni ove necessario.


2

Puoi anche trascinare un riconoscitore di gesti di tocco sulla vista dell'immagine in Storyboard. Quindi crea un'azione ctrl + dragper il codice.


1

Per gli amanti dei blocchi è possibile utilizzare ALActionBlocks per aggiungere l'azione dei gesti in blocco

__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];
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.