UIGestureRecognizer in UIImageView

179

Ich habe eine UIImageView, die ich in der Lage sein möchte, die Größe zu ändern und zu drehen usw.

Kann ein UIGestureRecognizerzum hinzugefügt werden UIImageView?

Ich möchte einen Rotations- und Pinch-Erkenner zu einem hinzufügen UIImageView, der zur Laufzeit erstellt wird.

Wie fügt man diese Erkenner hinzu?

System
quelle

Antworten:

426

Überprüfen Sie, dass userInteractionEnabledist YESauf der UIImageView. Anschließend können Sie eine Gestenerkennung hinzufügen.

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...
}
Abubakr Dar
quelle
5
Nein, dies zeigt nur, wie die Gestenerkenner hinzugefügt werden. Sie müssen das eigentliche Zoomen / Drehen in den Gestenhandlern selbst durchführen. Informationen zum Zoomen / Drehen finden Sie in der Beispiel-App Touches_GestureRecognizers .
77
+1 saß ewig hier und versuchte herauszufinden, warum meine Gesten nicht funktionieren würden. "Überprüfen Sie, ob userInteractionEnabled in der UIImageView JA ist." Vielen Dank!
Critter
1
Dies machte meine Arbeit definitiv einfacher, als zu versuchen, einem Erkenner, der auf die Gesamtansicht eingestellt ist, Grenzen zu setzen. Vielen Dank!
Josh Kovach
6
imageView.userInteractionEnabled = YES; das ist der Schlüssel! Danke dir.
HamasN
3
userInteractionEnabledmuss in Xcode 8 Objective-C / Swift
Leanne
76

Ja, ein UIGestureRecognizer kann zu einer UIImageView hinzugefügt werden. Wie in der anderen Antwort angegeben, ist es sehr wichtig, sich daran zu erinnern, die Benutzerinteraktion in der Bildansicht zu aktivieren, indem die userInteractionEnabledEigenschaft auf festgelegt wird YES. UIImageView erbt von UIView, dessen Benutzerinteraktionseigenschaft YESstandardmäßig festgelegt ist. Die Benutzerinteraktionseigenschaft von UIImageView ist jedoch NOstandardmäßig festgelegt.

Aus den UIImageView-Dokumenten:

Neue Bildansichtsobjekte sind so konfiguriert, dass Benutzerereignisse standardmäßig ignoriert werden. Wenn Sie Ereignisse in einer benutzerdefinierten Unterklasse von UIImageView verarbeiten möchten, müssen Sie den Wert der Eigenschaft userInteractionEnabled nach der Initialisierung des Objekts explizit in YES ändern.

Wie auch immer, auf den Großteil der Antwort. Hier ist ein Beispiel, wie Sie ein UIImageViewmit a UIPinchGestureRecognizer, a UIRotationGestureRecognizerund a erstellen UIPanGestureRecognizer.

viewDidLoadErstellen Sie zunächst in oder einer anderen Methode Ihrer Wahl eine Bildansicht, geben Sie ihr ein Bild und einen Rahmen und aktivieren Sie die Benutzerinteraktion. Erstellen Sie dann die drei Gesten wie folgt. Stellen Sie sicher, dass Sie die Eigenschaft delegate verwenden (höchstwahrscheinlich auf self eingestellt). Dies ist erforderlich, um mehrere Gesten gleichzeitig zu verwenden.

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

Hier sind die drei Methoden, die aufgerufen werden, wenn die Gesten in Ihrer Ansicht erkannt werden. In ihnen überprüfen wir den aktuellen Status der Geste. Wenn sie sich entweder in der begonnenen oder in der geänderten UIGestureRecognizerStateForm befindet, lesen wir die Skalierungs- / Rotations- / Übersetzungseigenschaft der Geste, wenden diese Daten auf eine affine Transformation an und wenden die affine Transformation auf das Bild an Zeigen Sie die Gesten an: Skalieren / Drehen / Verschieben.

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

Schließlich und vor allem müssen Sie die UIGestureRecognizerDelegate- Methode verwenden gestureRecognizer: shouldRecognizeSimultaneouslyWithGestureRecognizer, damit die Gesten gleichzeitig funktionieren. Wenn diese drei Gesten die einzigen drei Gesten sind, denen diese Klasse als Delegat zugewiesen ist, können Sie einfach YESwie unten gezeigt zurückkehren. Wenn Sie jedoch zusätzliche Gesten haben, denen diese Klasse als Delegat zugewiesen ist, müssen Sie dieser Methode möglicherweise Logik hinzufügen, um zu bestimmen, welche Geste welche ist, bevor sie alle zusammenarbeiten können.

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

Vergessen Sie nicht sicherzustellen, dass Ihre Klasse dem UIGestureRecognizerDelegate- Protokoll entspricht. Stellen Sie dazu sicher, dass Ihre Benutzeroberfläche ungefähr so ​​aussieht:

@interface MyClass : MySuperClass <UIGestureRecognizerDelegate>

Wenn Sie es vorziehen, selbst mit dem Code in einem funktionierenden Beispielprojekt zu spielen, finden Sie das von mir erstellte Beispielprojekt mit diesem Code hier.

Mick MacCallum
quelle
1
Dies ist bei weitem die beste Antwort, die ich je auf stackoverflow.com gesehen habe, vollständig detailliert, gut kommentiert und enthält sogar Quellcode auf git. Danke dafür
Alejandro Luengo
1
Klar, Schritt für Schritt, tolle Erklärung
Alvin
1
Vielen Dank, das hat auf ein oder zwei Seiten getan, was mehrere Dutzend Tutorials von Apple und anderen über Jahre hinweg nicht geschafft haben. Ich bin der Meinung, dass es in iOS viele andere Dinge geben muss, die möglich sind, aber aufgrund von Verschleierung und Missverständnissen gehen sie für uns verloren.
Zack Morris
Tolle Antwort, die beste. Vielen Dank für Ihre Geduld.
Jörg B Jorge
13

Swift 4.2

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

und wenn getippt:

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

Swift 2.0-Lösung

Sie erstellen im selben Herrenhaus einen Tipp-, Kneif- oder Wischgestenerkenner. Im Folgenden werde ich Sie durch 4 Schritte führen, um Ihren Erkenner zum Laufen zu bringen.

4 Schritte

1.) Erben Sie UIGestureRecognizerDelegatevon, indem Sie es Ihrer Klassensignatur hinzufügen.

class ViewController: UIViewController, UIGestureRecognizerDelegate {...}

2.) Steuern Sie das Ziehen von Ihrem Bild auf Ihren viewController, um ein IBOutlet zu erstellen:

@IBOutlet weak var tapView: UIImageView!

3.) Fügen Sie in Ihrem viewDidLoad den folgenden Code hinzu:

// 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.) Erstellen Sie die Funktion, die aufgerufen wird, wenn Sie auf Ihre Gestenerkennung tippen. (Sie können das ausschließen, = nilwenn Sie möchten).

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

Ihr endgültiger Code sollte ungefähr so ​​aussehen:

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)
    }
}
Dan Beaulieu
quelle
1
Ich habe hier einen Blog darüber geschrieben: codebeaulieu.com/3/UIGestureRecognier-programatisch
Dan Beaulieu
6

Ich habe dies gerade mit swift4 gemacht, indem ich 3 Gesten in einer einzigen Ansicht hinzugefügt habe

  1. UIPinchGestureRecognizer : Ansicht vergrößern und verkleinern .
  2. UIRotationGestureRecognizer : Drehen Sie die Ansicht.
  3. UIPanGestureRecognizer : Ziehen der Ansicht.

Hier mein Beispielcode

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
     }

}

Bei Fragen geben Sie einfach einen Kommentar ein. Danke

Leang Socheat
quelle
3

SWIFT 3 Beispiel

override func viewDidLoad() {

    self.backgroundImageView.addGestureRecognizer(
        UITapGestureRecognizer.init(target: self, action:#selector(didTapImageview(_:)))
    )

    self.backgroundImageView.isUserInteractionEnabled = true
}

func didTapImageview(_ sender: Any) {
    // do something
}

Keine Gestenerkennungsdelegierten oder andere Implementierungen, falls erforderlich.

Mourodrigo
quelle
2

Sie können auch einen Tippgestenerkenner in die Bildansicht ziehen Storyboard. Erstellen Sie dann eine Aktion mit ctrl + dragdem Code.

zevij
quelle
1

Für Blockliebhaber können Sie ALActionBlocks verwenden , um die Aktion von Gesten im Block hinzuzufügen

__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];
Dimo Hamdy
quelle