2011-11-13 10 views
25

を回して私のコードです:iOSのピンチスケールとツーフィンガーは、ここで同時に

のviewDidLoad:ピンチして回転するため

UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinch:)]; 
[self.canvas addGestureRecognizer:pinch]; 
pinch.delegate = self; 

UIRotationGestureRecognizer *twoFingersRotate = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(pinchRotate:)]; 
[[self canvas] addGestureRecognizer:twoFingersRotate]; 

twoFingersRotate.delegate = self; 

コード:

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

-(void)pinchRotate:(UIRotationGestureRecognizer*)rotate 
{ 
    SMImage *selectedImage = [DataCenter sharedDataCenter].selectedImage; 

    switch (rotate.state) 
    { 
     case UIGestureRecognizerStateBegan: 
     { 
      selectedImage.referenceTransform = selectedImage.transform; 
      break; 
     } 
     case UIGestureRecognizerStateChanged: 
     { 
      selectedImage.transform = CGAffineTransformRotate(selectedImage.referenceTransform, ([rotate rotation] * 55) * M_PI/180); 
      break; 
     } 

     default: 
      break; 
    } 
} 

-(void)pinch:(UIPinchGestureRecognizer*)pinch 
{ 
    SMImage *selectedImage = [DataCenter sharedDataCenter].selectedImage; 
    [self itemSelected]; 

    switch (pinch.state) 
    { 
     case UIGestureRecognizerStateBegan: 
     { 
      selectedImage.referenceTransform = selectedImage.transform; 
      break; 
     } 
     case UIGestureRecognizerStateChanged: 
     { 
      CGAffineTransform transform = CGAffineTransformScale(selectedImage.referenceTransform, pinch.scale, pinch.scale); 
      selectedImage.transform = transform; 
      break; 
     } 

     default: 
      break; 
    } 
} 

私の回転はその上で素晴らしい作品自分自身と私のスケールはそれ自身で素晴らしい作品ですが、一緒に働くことはありません。 1つは常に動作し、もう1つは動作しません。 shouldRecognizeSimultaneouslyWithGestureRecognizerを実装すると、2つのジェスチャが互いに闘っているように見え、結果が悪いようです。私は何が欠けていますか? (はい私は<UIGestureRecognizerDelegate>を実装しました)

答えて

33

いつもpinch:が呼び出されると、ピンチレコグナイザのスケールに基づいてトランスフォームを計算するだけです。 pinchRotate:が呼び出されるたびに、回転認識器の回転に基づいて変換を計算するだけです。スケールと回転を1つのトランスフォームに結合することは決してありません。

ここにアプローチがあります。

NSMutableSet *_activeRecognizers; 

viewDidLoadでそれを初期化します:

のアクションとして
_activeRecognizers = [NSMutableSet set]; 

いずれかを使用する方法の両方認識装置:

- (IBAction)handleGesture:(UIGestureRecognizer *)recognizer 
{ 
    SMImage *selectedImage = [DataCenter sharedDataCenter].selectedImage; 

    switch (recognizer.state) { 
     case UIGestureRecognizerStateBegan: 
      if (_activeRecognizers.count == 0) 
       selectedImage.referenceTransform = selectedImage.transform; 
      [_activeRecognizers addObject:recognizer]; 
      break; 

     case UIGestureRecognizerStateEnded: 
      selectedImage.referenceTransform = [self applyRecognizer:recognizer toTransform:selectedImage.referenceTransform]; 
      [_activeRecognizers removeObject:recognizer]; 
      break; 

     case UIGestureRecognizerStateChanged: { 
      CGAffineTransform transform = selectedImage.referenceTransform; 
      for (UIGestureRecognizer *recognizer in _activeRecognizers) 
       transform = [self applyRecognizer:recognizer toTransform:transform]; 
      selectedImage.transform = transform; 
      break; 
     } 

     default: 
      break; 
    } 
} 

あなたはよ自分で1つの新しいインスタンス変数、_activeRecognizersを与えますこのヘルパーメソッドが必要です:

- (CGAffineTransform)applyRecognizer:(UIGestureRecognizer *)recognizer toTransform:(CGAffineTransform)transform 
{ 
    if ([recognizer respondsToSelector:@selector(rotation)]) 
     return CGAffineTransformRotate(transform, [(UIRotationGestureRecognizer *)recognizer rotation]); 
    else if ([recognizer respondsToSelector:@selector(scale)]) { 
     CGFloat scale = [(UIPinchGestureRecognizer *)recognizer scale]; 
     return CGAffineTransformScale(transform, scale, scale); 
    } 
    else 
     return transform; 
} 

これは、回転とスケーリングだけを許可している場合に機能します。 (私もそれをテストしました!)

パンを追加する場合は、別のアクション方法を使用し、selectedImage.centerを調整してください。 selectedImage.transformを使用して回転とスケーリングを使用してパンニングを行うと、はるかに複雑になります。

+0

はあなたが私に私は両方を同時に適用することができる方法のコード例を与えることができピンチ?私のUIRotationGestureRecognizerには「スケール」プロパティがなく、UIPinchGestureRecognizerには「回転」プロパティがありません。そして私は同時にどちらのAffineを使うのか分からない。 – spentak

+0

美しく動作します。私はこの知識のおかげでずっと良いです! – spentak

+0

私は助けることができてうれしい。私はパンニングの方法について最後のビットを変更しました。また、ジェスチャーレコグナイザーをXIBに入れて、 'viewDidLoad'にコードをつける必要もありません。レコグナイザをビューにドラッグし、レコグナイザからFile's Ownerへのコントロールをドラッグして、レコグナイザのデリゲートとアクションアウトレットを接続します。 –

8

ジェスチャーデリゲートshouldRecognizeSimultaneouslyWithGestureRecognizerを実装して、同時に認識したいジェスチャーを配置する必要があります。

// ensure that the pinch and rotate gesture recognizers on a particular view can all recognize simultaneously 
// prevent other gesture recognizers from recognizing simultaneously 
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 
{ 
    // if the gesture recognizers's view isn't one of our views, don't allow simultaneous recognition 
    if (gestureRecognizer.view != firstView && gestureRecognizer.view != secondView) 
     return NO; 

    // if the gesture recognizers are on different views, don't allow simultaneous recognition 
    if (gestureRecognizer.view != otherGestureRecognizer.view) 
     return NO; 

    // if either of the gesture recognizers is the long press, don't allow simultaneous recognition 
    if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]] || [otherGestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) 
     return NO; 

    return YES; 
} 

このコードは、同時にジェスチャー認識機能を使用するビューに変更する必要があります。上記のコードは必要なものです。

+0

彼はすでに 'shouldRecognizeSimultaneouslyWithGestureRecognizer:'を持っています。これは常にYESを返します。 –

6

スウィフトパン、回転と3と

// MARK: - Gesturies 

    func transformUsingRecognizer(_ recognizer: UIGestureRecognizer, transform: CGAffineTransform) -> CGAffineTransform { 

     if let rotateRecognizer = recognizer as? UIRotationGestureRecognizer { 
      return transform.rotated(by: rotateRecognizer.rotation) 
     } 

     if let pinchRecognizer = recognizer as? UIPinchGestureRecognizer { 
      let scale = pinchRecognizer.scale 
      return transform.scaledBy(x: scale, y: scale) 
     } 

     if let panRecognizer = recognizer as? UIPanGestureRecognizer { 
      let deltaX = panRecognizer.translation(in: imageView).x 
      let deltaY = panRecognizer.translation(in: imageView).y 
      return transform.translatedBy(x: deltaX, y: deltaY) 
     } 

     return transform 
    } 

    var initialTransform: CGAffineTransform? 

    var gestures = Set<UIGestureRecognizer>(minimumCapacity: 3) 

    @IBAction func processTransform(_ sender: Any) { 

     let gesture = sender as! UIGestureRecognizer 

     switch gesture.state { 

     case .began: 
      if gestures.count == 0 { 
       initialTransform = imageView.transform 
      } 
      gestures.insert(gesture) 

     case .changed: 
      if var initial = initialTransform { 
       gestures.forEach({ (gesture) in 
        initial = transformUsingRecognizer(gesture, transform: initial) 
       }) 
       imageView.transform = initial 
      } 

     case .ended: 
      gestures.remove(gesture) 

     default: 
      break 
     } 
    } 

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { 

     return true 
    } 
+0

テストしましたか? –

+0

@RoiMulia確かに。それを実際のアプリで使ってみましょう。どうしましたか? –

+0

こんにちはマイク、大変申し訳ありません。何も間違っていない。ちょうどそれが安全であることを確認するために既にテストされているかどうかを尋ねたがっています(ちょうど私がいくつかの最終シナリオを見逃した場合) –

関連する問題