Here is my code:
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;
Code For Pinches and Rotates:
-(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; } }
My rotation works great on its own and my scale works great on its own, but they wont work together. One always works or the other doesn't. When I implement shouldRecognizeSimultaneouslyWithGestureRecognizer the two gestures seem to fight against each other and produce poor results. What am I missing? (Yes I have implemented <UIGestureRecognizerDelegate>
)
Every time pinch:
is called, you just compute the transform based on the pinch recognizer's scale. Every time pinchRotate:
is called, you just compute the transform based on the rotation recognizer's rotation. You never combine the scale and the rotation into one transform.
Here's an approach. Give yourself one new instance variable, _activeRecognizers
:
NSMutableSet *_activeRecognizers;
Initialize it in viewDidLoad
:
_activeRecognizers = [NSMutableSet set];
Use one method as the action for both recognizers:
- (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; } }
You'll need this helper method:
- (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; }
This works if you're just allowing rotating and scaling. (I even tested it!)
If you want to add panning, use a separate action method and just adjust selectedImage.center
. Trying to do panning with rotation and scaling using selectedImage.transform
is much more complicated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With