Reputation: 115
I am working on Scroll View with gestures. I added a UIView in Scroll View whose size is equal to the ScrollView content size. I want to apply the pinch gesture and rotate gesture on the View which is subview of ScrollView. I have done the work of the pinch gesture by using zoom property and delegate of the ScrollView which give me same effect which I want. But Rotation Gesture is creating Problem. When I add rotation gesture on the view then zooming of the scroll view also get disturb.
So how can i apply the pinch gesture and Rotate gesture on the Scroll View's subview whose size must be equal to the content size of the ScrollView initially.
Can anybody give me the way to do this!
This is the code of .m file, when we rotate the view it become invisible
#import "ViewController.h"
@interface ViewController ()
{
UIView *backgroundView;
UIScrollView *scrollView;
CGFloat lastRotation;
}
@end
@implementation ViewController
-(void)loadView
{
[super loadView];
//Scroll View
scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
scrollView.contentSize = self.view.frame.size;
scrollView.delegate = self;
scrollView.backgroundColor = [UIColor grayColor];
//Zooming factors of the Scroll View
scrollView.minimumZoomScale = 1.0;
scrollView.maximumZoomScale = 5.0f;
scrollView.zoomScale = 1.0;
[self.view addSubview:scrollView];
//Scroll View's subview
backgroundView = [[UIView alloc] initWithFrame:scrollView.frame];
[backgroundView setBackgroundColor:[UIColor orangeColor]];
[scrollView addSubview:backgroundView];
UIRotationGestureRecognizer *bgRotationGstr = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotateBackgroundView:)];
bgRotationGstr.delegate = self;
bgRotationGstr.cancelsTouchesInView = NO;
[backgroundView addGestureRecognizer:bgRotationGstr];
//Child of background view
UIView *childView = [[UIView alloc] initWithFrame:CGRectMake(20, 50, 100, 100)];
childView.backgroundColor = [UIColor grayColor];
[backgroundView addSubview:childView];
}
//Rotation of the background view
-(void)rotateBackgroundView:(UIRotationGestureRecognizer*)gesture
{
CGFloat rotation = 0.0 - (lastRotation - [(UIRotationGestureRecognizer*)gesture rotation]);
CGAffineTransform currentTransform = backgroundView.transform;
CGAffineTransform newTransform = CGAffineTransformRotate(currentTransform,rotation);
[backgroundView setTransform:newTransform];
lastRotation = [(UIRotationGestureRecognizer*)gesture rotation];
if (gesture.state == UIGestureRecognizerStateBegan || gesture.state == UIGestureRecognizerStateChanged)
{
scrollView.scrollEnabled = NO;
}
else if (gesture.state == UIGestureRecognizerStateEnded)
{
lastRotation = 0.0;
scrollView.scrollEnabled = YES;
return;
}
}
#pragma mark<UIScrollViewDelegate>
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return backgroundView;
}
#pragma mark<UIGetsureRecognizer>
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
return YES;
}
@end
Upvotes: 2
Views: 2123
Reputation: 1227
After many days of struggling I found a definitive solution in order to use UIScrollView integrated zoom behavior together with UIRotationGestureRecognizer working like a charm. You have to add a container dummy view as subview of the scroll view, and put the UIImageView as subview of the container view. Afterthat, return the container view in the viewForZoomingInScrollView method and add the UIRotationGestureRecognizer to the scrollview, applying CGAffineTransformRotate to the UIImageView. Finally, return true in the shouldRecognizeSimultaneouslyWithGestureRecognizer method. In this way the scrollView will capture both the two fingers rotation gesture and the pinch to zoom gesture: the zoom will be applied to the dummy view and rotation to the uiimageview, without conflicts between transformations.
In code: let's think to have a UIViewController presenting a UIScrollView. We want to use scrollview's zoom behaviour out of the box together with UIImageView rotation.
1) The controller (or any other object) containing UIScrollView must conforms to UIGestureRecognizerDelegate protocol.
In myViewController.h
@interface myViewController : UIViewController < UIGestureRecognizerDelegate> {
}
2) Create a UIScrollView, add a dummy view as subview and finally add a UIImageView as subview of the dummy view.
In myViewController.m
//Scrollview
myScrollView=[[UIScrollView alloc] initWithFrame:CGRectMake(0,0, view.frame.size.width, view.frame.size.height)];
myScrollView.delegate=self;
[view addSubview:myScrollView];
//Dummy View
UIView *dummyView=[[UIView alloc] initWithFrame:CGRectMake(0, 0, myScrollView.frame.size.width, myScrollView.frame.size.height)];
[self addSubview:dummyView];
//ImageView
imageView=[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, dummyView.frame.size.width, dummyView.frame.size.height)];
imageView.contentMode=UIViewContentModeScaleAspectFit;
[dummyView addSubview:imageView];
//Add rotation gesture to the scrollView
rotationGestureRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotate:)];
[myScrollView addGestureRecognizer:_rotationGestureRecognizer];
//Set the controller as delegate of the recognizer
rotationGestureRecognizer.delegate=self;
[...]
#pragma UIScrollViewDelegate
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
//Set the dummy view (imageview's superview) as view for zooming
return imageView.superview;
}
[...]
#pragma Mark - UIGestureRecognizerDelegate
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
//Make it possibile to recognize simultaneously pinch and rotation gestures
return TRUE;
}
[...]
- (IBAction) handleRotate:(UIRotationGestureRecognizer*)recognizer {
//Apply the rotation to imageView
imageView.transform = CGAffineTransformRotate(imageView.transform, recognizer.rotation);
recognizer.rotation = 0;
}
For simplyfing purposes, I wrote everything in the same controller. You are free to subclass the UIScrollView. Remember that the tricks are:
1) returning the container dummy view as viewForZoomingInScrollView so zoom will affect the container view and rotation will affect the uiimageview.
2) set the viewcontroller containing the scrollview as delegate of the rotation gesture recognizer and return TRUE for shouldRecognizeSimultaneouslyWithGestureRecognizer.
Upvotes: 3
Reputation: 463
UIGestureRecognizerDelegate
.- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{ return YES; }
rotationGeustureRecognozier.delegate = self;
// (the implement file)Upvotes: -1
Reputation: 2737
Try to put you scalable/rotatable content in a subview of your content view. ( Maybe you must set the "clip content" property of your content view to true - not sure )
This way the scrollview is not concerned anymore by transformations, since its content view stays still.
If you have to display the clipped content ( if you rotate a square, for example, the corners go out the initial area), recompute your content view and update the scrollview.
Since you gave the code, I suggest to try:
//Scroll View's subview
backgroundViewHolder = [[UIView alloc] initWithFrame:scrollView.frame];
[backgroundViewHolder setBackgroundColor:[UIColor orangeColor]];
[scrollView backgroundViewHolder];
//Holder View's subview
backgroundView = [[UIView alloc] initWithFrame:backgroundViewHolder.bounds];
[backgroundViewHolder addSubview:backgroundView];
Everything else should remain the same. This is just an idea... Not sure it is the right answer.
Upvotes: 0
Reputation: 17902
Add this to your .m
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
Also make sure you dont have exclusive touch enabled on any gesture recognizers.
Upvotes: 0