Sorry, in a rush but this is the code I used for one of my demo apps, it can pinch zoom and pan at the same time without using scrollview.
Don't forget to conform to UIGestureRecognizerDelegate protocol
If you're not able to get both pinch and pan at the same time, maybe it's because you're missing this method:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
Here is the full source code:
#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
isEditing = false;
photoView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
[photoView setImage:[UIImage imageNamed:@"photo.png"]];
photoView.hidden = YES;
maskView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
[maskView setImage:[UIImage imageNamed:@"maskguide.png"]];
maskView.hidden = YES;
displayImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)];
[panGesture setDelegate:self];
[pinchGesture setDelegate:self];
[photoView addGestureRecognizer:panGesture];
[photoView addGestureRecognizer:pinchGesture];
[photoView setUserInteractionEnabled:YES];
[panGesture release];
[pinchGesture release];
btnEdit = [[UIButton alloc] initWithFrame:CGRectMake(60, 400, 200, 50)];
[btnEdit setBackgroundColor:[UIColor blackColor]];
[btnEdit setTitle:@"Start Editing" forState:UIControlStateNormal];
[btnEdit addTarget:self action:@selector(toggleEditing) forControlEvents:UIControlEventTouchUpInside];
[[self view] addSubview:displayImage];
[[self view] addSubview:photoView];
[[self view] addSubview:maskView];
[[self view] addSubview:btnEdit];
[self updateMaskedImage];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
-(void)dealloc
{
[btnEdit release];
[super dealloc];
}
#pragma mark -
#pragma mark Update Masked Image Method
#pragma mark -
-(void)updateMaskedImage
{
maskView.hidden = YES;
UIImage *finalImage =
[self maskImage:[self captureView:self.view]
withMask:[UIImage imageNamed:@"mask.png"]];
maskView.hidden = NO;
//UIImage *finalImage = [self maskImage:photoView.image withMask:[UIImage imageNamed:@"mask.png"]];
[displayImage setImage:finalImage];
}
- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {
CGImageRef maskRef = maskImage.CGImage;
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), NULL, false);
CGImageRef masked = CGImageCreateWithMask([image CGImage], mask);
return [UIImage imageWithCGImage:masked];
}
#pragma mark -
#pragma mark Touches Began
#pragma mark -
// adjusts the editing flag to make dragging and drop work
-(void)toggleEditing
{
if(!isEditing)
{
isEditing = true;
NSLog(@"editing...");
[btnEdit setTitle:@"Stop Editing" forState:UIControlStateNormal];
displayImage.hidden = YES;
photoView.hidden = NO;
maskView.hidden = NO;
}
else
{
isEditing = false;
[self updateMaskedImage];
NSLog(@"stopped editting");
[btnEdit setTitle:@"Start Editing" forState:UIControlStateNormal];
displayImage.hidden = NO;
photoView.hidden = YES;
maskView.hidden = YES;
}
}
/*
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if(isEditing)
{
UITouch *finger = [touches anyObject];
CGPoint currentPosition = [finger locationInView:self.view];
//[maskView setCenter:currentPosition];
//[photoView setCenter:currentPosition];
if([touches count] == 1)
{
[photoView setCenter:currentPosition];
}
else if([touches count] == 2)
{
}
}
}
*/
-(void)handlePan:(UIPanGestureRecognizer *)recognizer
{
CGPoint translation = [recognizer translationInView:self.view];
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
}
-(void)handlePinch:(UIPinchGestureRecognizer *)recognizer
{
recognizer.view.transform = CGAffineTransformScale(recognizer.view.transform, recognizer.scale, recognizer.scale);
recognizer.scale = 1;
}
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
#pragma mark -
#pragma mark Capture Screen Function
#pragma mark -
- (UIImage*)captureView:(UIView *)yourView
{
UIGraphicsBeginImageContextWithOptions(yourView.bounds.size, yourView.opaque, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
[yourView.layer renderInContext:context];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
#pragma mark -
@end