UIImageViewのUIGestureRecognizer


179

私が持っているUIImageView、私はサイズを変更することができるようにしたい、と回転などを

UIGestureRecognizerに追加できますUIImageViewか?

UIImageView実行時に作成されるに、回転とピンチの認識機能を追加したいと思います。

これらの認識機能をどのように追加しますか?

回答:


426

チェックしuserInteractionEnabledているYESUIImageView。次に、ジェスチャー認識機能を追加できます。

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
いいえ、これはジェスチャー認識機能を追加する方法を示しています。実際のズーム/回転は、ジェスチャーハンドラーで行う必要があります。ズーム/回転の方法については、サンプルアプリTouches_GestureRecognizersをご覧ください。

77
ジェスチャーが機能しない理由を理解しようとする年齢層のために+1がここに座っていました。「UIImageViewでuserInteractionEnabledがYESであることを確認してください。」ありがとう!
クリッター、

1
これにより、全体的なビューに設定された認識機能に制限を設定するよりも、間違いなく私の作業が簡単になりました。ありがとう!
Josh Kovach、2011

6
imageView.userInteractionEnabled = YES; これが鍵です!ありがとうございました。
HamasN 2013年

3
userInteractionEnabledXcode 8 Objective-C / SwiftでYES / trueに設定する必要があります
リーン

76

はい、UIGestureRecognizerをUIImageViewに追加できます。他の回答で述べたように、userInteractionEnabledプロパティをに設定することにより、画像ビューでのユーザー操作を有効にすることを覚えておくことは非常に重要YESです。UIImageViewはUIViewから継承YESします。UIViewのユーザー操作プロパティはデフォルトで設定されていますが、UIImageViewのユーザー操作プロパティはNOデフォルトで設定されています。

UIImageViewドキュメントから

新しい画像ビューオブジェクトは、デフォルトでユーザーイベントを無視するように設定されています。UIImageViewのカスタムサブクラスでイベントを処理する場合は、オブジェクトの初期化後に、userInteractionEnabledプロパティの値を明示的にYESに変更する必要があります。

とにかく、答えの大部分。ここで作成する方法の例ですUIImageViewUIPinchGestureRecognizerUIRotationGestureRecognizerUIPanGestureRecognizer

まず、viewDidLoadまたはその他の選択した方法で、画像ビューを作成し、画像とフレームを指定して、ユーザー操作を有効にします。次に、次の3つのジェスチャーを作成します。必ずデリゲートプロパティを使用してください(ほとんどの場合、セルフに設定されています)。これは、複数のジェスチャーを同時に使用するために必要です。

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

ビューのジェスチャーが検出されたときに呼び出される3つのメソッドは次のとおりです。それらの内部で、ジェスチャーの現在の状態を確認し、それが開始または変更のいずれかである場合はUIGestureRecognizerState、ジェスチャーのスケール/回転/変換プロパティを読み取り、そのデータをアフィン変換に適用し、アフィン変換を画像に適用します表示し、ジェスチャーのスケール/回転/平行移動をリセットします。

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

最後に、非常に重要なことですが、UIGestureRecognizerDelegateメソッドgestureRecognizer: shouldRecognizeSimultaneouslyWithGestureRecognizerを使用して、ジェスチャーを同時に機能させる必要があります。これらの3つのジェスチャーが、このクラスがデリゲートとして割り当てられている唯一の3つのジェスチャーである場合、YES以下に示すように単純に戻ることができます。ただし、このクラスがデリゲートとして割り当てられているジェスチャーがある場合は、このメソッドにロジックを追加して、すべてのジェスチャーを連携させる前に、どのジェスチャーであるかを判別する必要がある場合があります。

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

クラスがUIGestureRecognizerDelegateプロトコルに準拠していることを確認することを忘れないでください。そのためには、インターフェースが次のようになっていることを確認してください。

@interface MyClass : MySuperClass <UIGestureRecognizerDelegate>

作業中のサンプルプロジェクトのコードを自分で再生したい場合は、このコードを含む私が作成したサンプルプロジェクトをここで見つけることができます。


1
これは、stackoverflow.comでこれまでに見た中で最も優れた回答であり、完全に詳細でよくコメントされており、gitのソースコードも含まれています。ありがとう
アレハンドロルエンゴ2014

1
わかりやすく、一歩一歩、素晴らしい説明
Alvin

1
ありがとう、それは1ページか2ページで終わりましたが、Appleや他の人たちによる長年にわたる数十のチュートリアルは失敗しました。iOSには他にも可能なことはたくさんあると思いますが、難読化と誤解により、それらは失われています。
Zack Morris

すばらしい答え、最高の答えです。お待ちいただき、ありがとうございます。
Jorg B Jorge

13

Swift 4.2

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

タップすると:

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

11

Swift 2.0ソリューション

同じ邸宅でタップ、ピンチ、またはスワイプのジェスチャー認識機能を作成します。以下では、認識機能を起動して実行するための4つの手順を説明します。

4ステップ

1.)UIGestureRecognizerDelegateクラスシグネチャに追加して継承します。

class ViewController: UIViewController, UIGestureRecognizerDelegate {...}

2.)画像からviewControllerへのドラッグを制御して、IBOutletを作成します。

@IBOutlet weak var tapView: UIImageView!

3.) viewDidLoadに次のコードを追加します。

// 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.)ジェスチャー認識機能がタップされたときに呼び出される関数を作成します。(= nil選択した場合は除外できます)。

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

最終的なコードは次のようになります。

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

1
私はこれについてここにブログを書いた:codebeaulieu.com/3/UIGestureRecognier-programatically
Dan Beaulieu

6

私はこれをswift4で3つのジェスチャーを単一のビューに追加してこれを行いました

  1. UIPinchGestureRecognizer:ビューを拡大および縮小します。
  2. UIRotationGestureRecognizer:ビューを回転させます。
  3. UIPanGestureRecognizer:ビューをドラッグします。

ここに私のサンプルコード

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
     }

}

質問があれば入力してコメントしてください。ありがとうございました


3

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
}

必要に応じて、ジェスチャ認識エージェントデリゲートまたはその他の実装はありません。


2

タップジェスチャ認識機能をの画像ビューにドラッグすることもできますStoryboard。次にctrl + drag、コードによってアクションを作成します。


1

ブロック愛好家の場合、ALActionBlocksを使用してブロックにジェスチャーのアクションを追加できます

__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];
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.