Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iPhone iOS how to make UIRotationGestureRecognizer and UIPinchGestureRecognizer to work together to scale and rotate a UIView with subviews?

I'm implementing a drag/drop/resize/rotate labels within my app. So far everything is working except for the UIRotationGestureRecognizer gesture. More specifically, it does not work with the UIPinchGestureRecognizer gesture.

Normally the two gestures compete for two finger touches, so I'm running them in parallel. Below are my 2 methods that the gesture recognizers invoke.

When doing the rotation gesture, the view spins wildly around it's center, with it's height and width changing as follows: height becomes width, width slowly turns into height. Eventually, the view disappears.

Within the view, I have another auto-resizing view. Normally, the pinch gesture automatically resizes the subviews as well, but in this case the subviews with autoresizing masks disappear. The subviews have height and width springs and left/top strut.

What am I doing wrong? How can I both resize and scale a UIView with gestures?

All the delegate methods and connections are setup properly. I need to understand how to handle the order in which the recognizers would be applying the scaling and rotation.

//makes 2 gesture recognizers behave together
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    return YES;
}

- (IBAction)handleRotationFrom:(id)sender {
    NSLog(@"Gesture rotation %.1f", rotationGestureRecognizer.rotation);

//attempt to continuously rotate the label, starting with a remembered rotation    

    float rotation = atan2(activeCompanionLabelView.transform.b, activeCompanionLabelView.transform.a);
    NSLog(@"existing rotation %.1f", rotation);

//    rotation = rotation<0?(2*M_PI)-fabs(rotation):rotation;
    rotation +=rotationGestureRecognizer.rotation;

    NSLog(@"*** gesture rotation %.1f sum: %.1f, saved: %.1f",rotationGestureRecognizer.rotation, rotation, activeCompanionLabelView.savedRotation);
    activeCompanionLabelView.transform = CGAffineTransformMakeRotation((rotation));
    activeCompanionLabelView.savedRotation = rotation;
}

- (IBAction)handlePinch:(id)sender {
    NSLog(@"pinch %.2f", pinchGestureRecognizer.scale);

//resize, keeping the origin where it was before

    activeCompanionLabelView.frame = CGRectMake(activeLabelContainerFrame.origin.x, activeLabelContainerFrame.origin.y, activeLabelContainerFrame.size.width*pinchGestureRecognizer.scale, activeLabelContainerFrame.size.height*pinchGestureRecognizer.scale);    



}
like image 986
Alex Stone Avatar asked Mar 17 '12 15:03

Alex Stone


1 Answers

If you want two gestureRecognisers to run in parallel (simultaneously) your view should implement <UIGestureRecognizerDelegate>.

Also, you should make it a delegate of both gestureRecognizers.

rotationGestureRecognizer.delegate=self;
pinchGestureRecognizer.delegate=self;

And you also should implement shouldRecognizeSimultaneouslyWithGestureRecognizer: method:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {

    return YES;
}

NOTE: if you have more then this two gestureRecognisers in your view you're gonna have to add some identity checking in this method.

EDIT:

Just found Ole Begemann's article on this topic: Gesture Recognition on iOS with Attention to Detail

like image 186
Rok Jarc Avatar answered Oct 03 '22 21:10

Rok Jarc