Limitting UIImageView size while using CGAffineTransform - iphone

I want to limit my uiimageview size while using CGAffineTransform. I am limitting scale but I can't limit the size of the my uiimageview. When I run the app I see it is limitted but in the background the size of my uiimageview keeps increasing. How can I make this?
Here is my code:
- (id)initWithFrame:(CGRect)frame
{
if ([super initWithFrame:frame] == nil) {
return nil;
}
originalTransform = CGAffineTransformIdentity;
touchBeginPoints = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
self.userInteractionEnabled = YES;
self.multipleTouchEnabled = YES;
self.exclusiveTouch = YES;
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSMutableSet *currentTouches = [[[event touchesForView:self] mutableCopy] autorelease];
[currentTouches minusSet:touches];
if ([currentTouches count] > 0) {
[self updateOriginalTransformForTouches:currentTouches];
[self cacheBeginPointForTouches:currentTouches];
}
[super touchesBegan:touches withEvent:event];
[self cacheBeginPointForTouches:touches];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
CGAffineTransform incrementalTransform = [self incrementalTransformWithTouches:[event touchesForView:self]];
self.transform = CGAffineTransformConcat(originalTransform, incrementalTransform);
CGAffineTransform transform = self.transform;
float scale = sqrt(transform.a*transform.a + transform.c*transform.c);
NSLog(#"%f",self.frame.size.height);
if (scale > SCALE_MAX){
self.transform = CGAffineTransformScale(transform, SCALE_MAX/scale, SCALE_MAX/scale);
}
else if (scale < SCALE_MIN){
self.transform = CGAffineTransformScale(transform, SCALE_MIN/scale, SCALE_MIN/scale);
}
[super touchesMoved:touches withEvent:event];
}
-(void)updateOriginalTransformForTouches:(NSSet *)touches{
CGAffineTransform transform = self.transform;
float scale = sqrt(transform.a*transform.a + transform.c*transform.c);
if (scale > SCALE_MAX){
self.transform = CGAffineTransformScale(transform, SCALE_MAX/scale, SCALE_MAX/scale);
}
else if (scale < SCALE_MIN){
self.transform = CGAffineTransformScale(transform, SCALE_MIN/scale, SCALE_MIN/scale);
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
if (touch.tapCount >= 2) {
[self.superview bringSubviewToFront:self];
}
}
[self updateOriginalTransformForTouches:[event touchesForView:self]];
[self removeTouchesFromCache:touches];
NSMutableSet *remainingTouches = [[[event touchesForView:self] mutableCopy] autorelease];
[remainingTouches minusSet:touches];
[super touchesEnded:touches withEvent:event];
[self cacheBeginPointForTouches:remainingTouches];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[self touchesEnded:touches withEvent:event];
}

You can know CGRect of UIImagView before applying transform on it like below example :
//Create transform
CGAffineTransform scaleTransform = CGAffineTransformMakeScale(1.2, 1.2);
//Apply transform on UIImageView to get CGRect
CRect newRect = CGRectApplyAffineTransform(yourImgView.frame, scaleTransform);
//Check if rect is in valid limitation
if(newRect.size.height > 200 && newRect.size.width >200) //your condition to limit UIImageView's Size
{
//Valid so apply transform
yourImageView.transform = scaleTransform
}
else
{
//rect increases so no transform
// no transform to UIImageView
NSLog(#"%#",NSStringFromCGRect(yourImageView.frame))
}

I was facing the a similar problem, I have an image view that's rotating according to compass heading data and also has to move position according to device change in interface orientation
I created a tempImageView to help maintain frame, and kept reseting it with every change in device orientation
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
// equal tempImageView to imageView
_tempImageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.view.frame.size.width-75, 150, 64, 61)];
[_tempImageView setImage:[UIImage imageNamed:#"image.gif"]];
_tempImageView.transform = _imageView.transform;
// reset imageView
[_imageView removeFromSuperview];
_imageView = _tempImageView;
[self.view insertSubview:_imageView atIndex:1];
}

Related

ios ktphotobrowser set contentsize of scrollview to zommed image size

i am using ktphotobrowser for my app. in big image screen (ktphotoscrollviewcontroller) when i zoom image with two times tapping, the content size of scrollview (ktphotoview - it is an uiscrollview object) grows to bound.size * maximumzoomscale but my zoomed image size still smaller than contentsize of scrollview. both zoomed image size and the scrollview's contentsize must be same so where can i do these calculation on the code?
if anybody use ktphotobrowser could help me about this problem, i will very appreciate.
i find the tap count but after this code i couldnt find where is the contentsize growing (zoom) or image growing (zoom) code
below you can find the whole code of ktphotoview.h page where the tapping count and zooming actions are coded:
#import "KTPhotoView.h"
#import "KTPhotoScrollViewController.h"
#import <QuartzCore/QuartzCore.h>
#interface KTPhotoView (KTPrivateMethods)
- (void)loadSubviewsWithFrame:(CGRect)frame;
- (BOOL)isZoomed;
- (void)toggleChromeDisplay;
#end
#implementation KTPhotoView
#synthesize scroller = scroller_;
#synthesize index = index_;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setDelegate:self];
[self setMaximumZoomScale:2.0];
[self setShowsHorizontalScrollIndicator:NO];
[self setShowsVerticalScrollIndicator:NO];
[self loadSubviewsWithFrame:frame];
NSLog(#"scrollview2 %f",self.contentSize.height);
}
return self;
}
- (void)loadSubviewsWithFrame:(CGRect)frame
{
imageView_ = [[UIImageView alloc] initWithFrame:frame];
[imageView_ setContentMode:UIViewContentModeScaleAspectFit];
[self addSubview:imageView_];
}
- (void)setImage:(UIImage *)newImage
{
[imageView_ setImage:newImage];
}
- (void)layoutSubviews
{
[super layoutSubviews];
if ([self isZoomed] == NO && CGRectEqualToRect([self bounds], [imageView_ frame]) == NO) {
[imageView_ setFrame:[self bounds]];
}
}
- (void)toggleChromeDisplay
{
if (scroller_) {
[scroller_ toggleChromeDisplay];
}
}
- (BOOL)isZoomed
{
return !([self zoomScale] == [self minimumZoomScale]);
}
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center
{
CGRect zoomRect;
// the zoom rect is in the content view's coordinates.
// At a zoom scale of 1.0, it would be the size of the imageScrollView's bounds.
// As the zoom scale decreases, so more content is visible, the size of the rect grows.
zoomRect.size.height = [self frame].size.height / scale;
zoomRect.size.width = [self frame].size.width / scale;
// choose an origin so as to get the right center.
zoomRect.origin.x = center.x - (zoomRect.size.width / 2.0);
zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0);
NSLog(#"zoomRectHeight %f",[self frame].size.height);
return zoomRect;
}
- (void)zoomToLocation:(CGPoint)location
{
float newScale;
CGRect zoomRect;
if ([self isZoomed]) {
zoomRect = [self bounds];
} else {
newScale = [self maximumZoomScale];
zoomRect = [self zoomRectForScale:newScale withCenter:location];
}
// NSLog(#"zoomRectHeight %f",location.);
[self zoomToRect:zoomRect animated:YES];
}
- (void)turnOffZoom
{
if ([self isZoomed]) {
[self zoomToLocation:CGPointZero];
}
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
if ([touch view] == self) {
if ([touch tapCount] == 2) {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:#selector(toggleChromeDisplay) object:nil];
[self zoomToLocation:[touch locationInView:self]];
}
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
if ([touch view] == self) {
if ([touch tapCount] == 1) {
[self performSelector:#selector(toggleChromeDisplay) withObject:nil afterDelay:0.5];
}
}
}
#pragma mark -
#pragma mark UIScrollViewDelegate Methods
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
UIView *viewToZoom = imageView_;
NSLog(#"scrollview %f",self.contentSize.height);
return viewToZoom;
}
i use the below code in ktphotoview.m file to solve my problem hope this helps:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
if ([touch view] == self) {
if ([touch tapCount] == 2) {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:#selector(toggleChromeDisplay) object:nil];
[self zoomToRect:[self zoomRectForScale:[self maximumZoomScale] withCenter:[touch locationInView:self]] animated:YES];
float abc=(self.contentSize.height-(imageView_.image.size.height*320/imageView_.image.size.width*self.maximumZoomScale))/2 *-1;
[self setContentInset:UIEdgeInsetsMake(abc, 0, abc, 0)];
}
}
}

how to create a path using coregraphics?

i want to create a path.something like i touch the screen and draw line in touchmove event.when line intersect from starting point.fill that path using any colour.
now see in the image i've drawn a line.i just want to detect if line intersects again to start point.then fill that path with my own desired color.also i m using core graphics to draw line but it's very slow on real device.could you tell me a way to improve speed?
Header:
#import <UIKit/UIKit.h>
#interface myView : UIView {
CGMutablePathRef path;
CGPathRef drawingPath;
CGRect start;
BOOL outsideStart;
}
#end
Implementation:
#import "myView.h"
#implementation myView
- (id) init {
if (self = [super init]) {
self.userInteractionEnabled = YES;
self.multipleTouchEnabled = NO;
}
}
- (void) finishPath {
if (drawingPath) {
CGPathRelease(drawingPath);
}
CGPathCloseSubpath(path);
drawingPath = CGPathCreateCopy(path);
CGPathRelease(path);
path = NULL;
[self setNeedsDisplay];
return;
}
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
path = CGPathCreateMutable();
UITouch *t = [touches anyObject];
CGPoint p = [t locationInView:self];
start = CGRectZero;
start.origin = p;
start = CGRectInset(start,-10, -10);
outsideStart = NO;
CGPathMoveToPoint(path, NULL, p.x, p.y);
}
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if (!path) {
return;
}
UITouch *t = [touches anyObject];
CGPoint p = [t locationInView:self];
if (CGRectContainsPoint(start,p)) {
if (outsideStart) {
[self finishPath];
}
} else {
outsideStart = YES;
}
CGPathAddLineToPoint(path,NULL,p.x,p.y);
[self setNeedsDisplay];
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if (!path) {
return;
}
[self finishPath];
}
- (void) touchesCanceled:(NSSet *)touches withEvent:(UIEvent *)event {
if (!path) {
return;
}
CGPathRelease(path);
path = NULL;
}
- (void) drawInRect:(CGRect)rect {
CGContextRef g = UIGraphicsGetCurrentContext();
if (drawingPath) {
CGContextAddPath(g,drawingPath);
[[UIColor redColor] setFill];
[[UIColor blackColor] setStroke];
CGContextDrawPath(g,kCGPathFillStroke);
}
if (path) {
CGContextAddPath(g,path);
[[UIColor blackColor] setStroke];
CGContextDrawPath(g,kCGPathStroke);
}
}
- (void) dealloc {
if (drawingPath) {
CGPathRelease(drawingPath);
}
if (path) {
CGPathRelease(path);
}
[super dealloc];
}
#end
Note that you will probably want to do something so you aren't actually calling setNeedsDisplay every time the path changes. This can get very slow. Suggestions include having an NSTimer that fires every x milliseconds to check if it needs to redisplay and do so if it does, or only redrawing if the touch has moved a significant distance.
Maybe it can be useful to you link text
Core Graphics should definitely not be using [self setNeedsDisplay] every time the image changes, which is probably why your code is so slow on the device. Drawing is slow. If you use OpenGL ES to draw the lines, it will be much quicker, at the expense of being more difficult to understand.

Move an UIImageView around in a UIScrollView

I'm creating an application where I want to let the user move (not pan) an UIImageView around by dragging it on the screen. Additionally, I want the user to be able to zoom the UIImageView in and out.
As such I've been using a custom UIScrollView that forwards single touches to the 'contentView':
#implementation JM_UIScrollView
- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view
{
NSSet *allTouches = [event allTouches];
NSLog(#"Checking for touches: %d", [allTouches count]);
if ([allTouches count] == 1) {
return YES;
}
return NO;
}
#end
Along with a custom UIImageView that implements touchesBegan and touchesMoved to determine where to move the UIImageView:
#implementation JM_UIImageView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSSet *allTouches = [event allTouches];
if ([allTouches count] == 0)
return;
UITouch *firstTouch = [[allTouches allObjects] objectAtIndex: 0];
CGPoint touchLoc = [firstTouch locationInView: [self superview]];
touchOffset= CGPointMake(touchLoc.x-self.center.x,touchLoc.y-self.center.y);
NSLog(#"Currently at: %3.3f x %3.3f", touchLoc.x, touchLoc.y);
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSSet *allTouches = [event allTouches];
if ([allTouches count] == 0)
return;
UITouch *firstTouch = [[allTouches allObjects] objectAtIndex: 0];
CGPoint touchLoc = [firstTouch locationInView: [self superview]];
if ([allTouches count] == 1)
{
if ([firstTouch view] == self)
{
touchLoc.x -= touchOffset.x;
touchLoc.y -= touchOffset.y;
NSLog(#"Moved to: %3.3f x %3.3f", touchLoc.x, touchLoc.y);
self.center = touchLoc;
}
}
}
#end
This is then all glued together:
scrollView = [[JM_UIScrollView alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
scrollView.delegate = self;
scrollView.bouncesZoom = YES;
scrollView.scrollEnabled = NO;
scrollView.backgroundColor = [UIColor redColor];
scrollView.clipsToBounds = YES;
UIImage *image = [UIImage imageNamed:#"berg.jpg"];
imageView = [[JM_UIImageView alloc] initWithFrame: CGRectMake(0, 0, 140, 230)];
imageView.image = image;
imageView.center = CGPointMake(200,300);
[imageView setUserInteractionEnabled: YES];
[scrollView addSubview: imageView];
scrollView.contentSize = CGSizeMake(140,230);
scrollView.minimumZoomScale = 0.2;
scrollView.maximumZoomScale = 1.1;
[window addSubview: scrollView];
// Override point for customization after application launch
[window makeKeyAndVisible];
The problem:
When I start the application, I can move the UIImageView just fine and fluently. I can zoom-in and still be able to move it around.
However, it seems that whenever I zoom back out to the maximum level I seem then unable to move the UIImageView around anymore. It will jump at times, but by a maximum of 10 pixels. Use of NSLog() shows the touchesBegan/touchesMoved methods on the JM_UIImageView are no longer called.
Does anyone have any idea on what I might be missing here?
EDIT:
Would also accept an answer for wether or not this is the only way of implementing pinch-zooming with the zoombounce animation.

How do I display more than one page from a PDF?

Hello I want to make an application in which I have to display pdffile on iphone screen, which has a functionality of zooming. I have multiple pages of pdffile, but the problem is i can get display only one page.
Here is the code :
/*myView.m*/
#implementation MyView
- (void)configureTiledLayer {
if([global getfirsttime] == 0)
{
[global fetchpageCtr : 1];
[global fetchfirsttime:1];
}
zoom = 1.0f;
tiledLayer = [CATiledLayer layer];
TiledDelegate *delegate = [[TiledDelegate alloc] init];
tiledLayer.delegate = delegate;
// get tiledLayer size
CGRect pageRect = CGPDFPageGetBoxRect(delegate.map, kCGPDFCropBox);
int w = pageRect.size.width;
int h = pageRect.size.height;
NSLog(#"height==%d,weight=%d",h,w);
// get level count
int levels = 1;
while (w > 1 && h > 1) {
levels++;
w = w >> 1;
h = h >> 1;
}
NSLog(#"Layer create");
// set the levels of detail
tiledLayer.levelsOfDetail = levels;
// set the bias for how many 'zoom in' levels there are
tiledLayer.levelsOfDetailBias = 5;
// setup the size and position of the tiled layer
CGFloat width = CGRectGetWidth(pageRect);
CGFloat height = CGRectGetHeight(pageRect);
tiledLayer.bounds = CGRectMake(0.0f, 0.0f, width, height);
CGFloat x = width * tiledLayer.anchorPoint.x;
CGFloat y = -height * tiledLayer.anchorPoint.y;
tiledLayer.position = CGPointMake(x * zoom, y * zoom);
tiledLayer.transform = CATransform3DMakeScale(zoom, zoom, 1.0f);
// transform the super layer so things draw 'right side up'
CATransform3D superTransform = CATransform3DMakeTranslation(0.0f, self.bounds.size.height, 0.0f);
self.layer.transform = CATransform3DScale(superTransform, 1.0, -1.0f, 1.0f);
[self.layer addSublayer:tiledLayer];
[tiledLayer setNeedsDisplay];
moving = NO;
NSLog(#"in layer");
}
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor blueColor];
[self configureTiledLayer];
}
return self;
}
- (id)initWithCoder:(NSCoder *)coder {
if (self = [super initWithCoder:coder]) {
[self configureTiledLayer];
}
return self;
}
- (void)setZoom:(CGFloat)newZoom {
zoom = newZoom;
tiledLayer.transform = CATransform3DMakeScale(zoom, zoom, 1.0f);
}
- (void)zoomIn {
[self setZoom:zoom * 2.0f];
}
- (void)zoomOut {
[self setZoom:zoom * 0.5f];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if(touches.count == 1) {
previousPoint = [[touches anyObject] locationInView:self];
} else if(touches.count == 2) {
// pinch zoom
pinchZoom = YES;
NSArray *touches = [event.allTouches allObjects];
CGPoint pointOne = [[touches objectAtIndex:0] locationInView:self];
CGPoint pointTwo = [[touches objectAtIndex:1] locationInView:self];
previousDistance = sqrt(pow(pointOne.x - pointTwo.x, 2.0f) +
pow(pointOne.y - pointTwo.y, 2.0f));
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if(touches.count == 1) {
CGPoint currentPoint = [[touches anyObject] locationInView:self];
CGPoint delta = CGPointMake(currentPoint.x - previousPoint.x, currentPoint.y - previousPoint.y);
tiledLayer.position = CGPointMake(tiledLayer.position.x + delta.x * zoom,
tiledLayer.position.y + delta.y * zoom);
previousPoint = currentPoint;
moving = YES;
} else if(touches.count == 2) {
// pinch zoom stuff
NSArray *touches = [event.allTouches allObjects];
CGPoint pointOne = [[touches objectAtIndex:0] locationInView:self];
CGPoint pointTwo = [[touches objectAtIndex:1] locationInView:self];
CGFloat distance = sqrt(pow(pointOne.x - pointTwo.x, 2.0f) +
pow(pointOne.y - pointTwo.y, 2.0f));
CGFloat newZoom = fabs(zoom + (distance - previousDistance) / previousDistance);
[self setZoom:newZoom];
previousDistance = distance;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if(!moving) {
if(touches.count == 1) {
// realy should recenter on a click but I'm being lazy
if([[touches anyObject] tapCount] == 2) {
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[self zoomOut];
} else {
[self performSelector:#selector(zoomIn) withObject:nil afterDelay:0.25];
}
}
} else {
moving = NO;
}
}
- (void)dealloc {
[tiledLayer release];
[super dealloc];
}
/*TiledDelegate.m*/
#implementation TiledDelegate
- (CGPDFDocumentRef)sfMuni {
if(NULL == sfMuni) {
NSString *path = [[NSBundle mainBundle] pathForResource:#"Hunting-TrappingSynopsis_0910" ofType:#"pdf"];
NSURL *docURL = [NSURL fileURLWithPath:path];
sfMuni = CGPDFDocumentCreateWithURL((CFURLRef)docURL);
}
return sfMuni;
}
- (CGPDFPageRef)map {
int temppageno = [global getpageCtr];
NSLog(#"page ctr ==%d ",temppageno);
if(NULL == map) {
map = CGPDFDocumentGetPage(self.sfMuni, temppageno);
}
return map;
}
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
NSLog(#"\ndrawLayer:inContext:");
NSLog(#"ctm = %#", NSStringFromCGAffineTransform(CGContextGetCTM(ctx)));
NSLog(#"box = %#\n", NSStringFromCGRect(CGContextGetClipBoundingBox(ctx)));
CGContextDrawPDFPage(ctx, self.map);
}
- (void)dealloc {
CGPDFPageRelease(map);
CGPDFDocumentRelease(sfMuni);
[super dealloc];
}
/*TiledLayerAppDelegate*/
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}
- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}
/*TiledLayerViewController*/
- (void)viewDidLoad
{
l_pagectr = 2;
UIButton *btn1 = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
btn1.frame = CGRectMake(0,0,70,50);
[btn1 setBackgroundColor: [UIColor whiteColor]];
btn1.exclusiveTouch = YES;
[btn1 setTitle:#"Next" forState:UIControlStateNormal];
[btn1 setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[btn1 addTarget:self action:#selector(NextPressed:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn1];
}
-(IBAction)NextPressed : (id)sender
{
[global fetchpageCtr : l_pagectr++];
MyView *myview1=[[MyView alloc]init];
}
#end
Here when I pressed Next button it will have to display me the nest page but will display me the same page.I also get the page referance in "CGPDFPageRef" incremented but not displayed.
Plz help me for this.
Why don't you just use UIWebView? It renders PDF and offers zoom controls. No need to reinvent the wheel. Here is documentation for UIWebView.

Multi touch is not working perfectly on UIImageView

I am doing multi touch on UImageView means zoom in and zoom out on image view. I am using followng code but it doesn't work very well. Can anyone look at this code,
#import "ZoomingImageView.h"
#implementation ZoomingImageView
#synthesize zoomed;
#synthesize moved;
define HORIZ_SWIPE_DRAG_MIN 24
define VERT_SWIPE_DRAG_MAX 24
define TAP_MIN_DRAG 10
CGPoint startTouchPosition;
CGFloat initialDistance;
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// Initialization code
moved = NO;
zoomed = NO;
}
return self;
}
- (void)drawRect:(CGRect)rect {
// Drawing code
}
- (void)dealloc {
if([timer isValid])
[timer invalidate];
[super dealloc];
}
- (void) setImage: (UIImage*)img
{
zoomed = NO;
moved = NO;
self.transform = CGAffineTransformIdentity;
[super setImage:img];
}
- (CGFloat)distanceBetweenTwoPoints:(CGPoint)fromPoint toPoint:(CGPoint)toPoint {
float x = toPoint.x - fromPoint.x;
float y = toPoint.y - fromPoint.y;
return sqrt(x * x + y * y);
}
- (CGFloat)scaleAmount: (CGFloat)delta {
CGFloat pix = sqrt(self.frame.size.width * self.frame.size.height);
CGFloat scale = 1.0 + (delta / pix);
return scale;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if([timer isValid])
[timer invalidate];
moved = NO;
switch ([touches count]) {
case 1:
{
// single touch
UITouch * touch = [touches anyObject];
startTouchPosition = [touch locationInView:self];
initialDistance = -1;
break;
}
default:
{
// multi touch
UITouch *touch1 = [[touches allObjects] objectAtIndex:0];
UITouch *touch2 = [[touches allObjects] objectAtIndex:1];
initialDistance = [self distanceBetweenTwoPoints:[touch1 locationInView:self]
toPoint:[touch2 locationInView:self]];
break;
}
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch1 = [[touches allObjects] objectAtIndex:0];
if([timer isValid])
[timer invalidate];
/*if ([touches count] == 1) {
CGPoint pos = [touch1 locationInView:self];
self.transform = CGAffineTransformTranslate(self.transform, pos.x - startTouchPosition.x, pos.y - startTouchPosition.y);
moved = YES;
return;
}****/
if ((initialDistance > 0) && ([touches count] > 1)) {
UITouch *touch2 = [[touches allObjects] objectAtIndex:1];
CGFloat currentDistance = [self distanceBetweenTwoPoints:[touch1 locationInView:self]
toPoint:[touch2 locationInView:self]];
CGFloat movement = currentDistance - initialDistance;
NSLog(#"Touch moved: %f", movement);
CGFloat scale = [self scaleAmount: movement];
self.transform = CGAffineTransformScale(self.transform, scale, scale);
// }
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch1 = [[touches allObjects] objectAtIndex:0];
if ([touches count] == 1) {
// double tap to reset to default size
if ([touch1 tapCount] > 1) {
if (zoomed) {
self.transform = CGAffineTransformIdentity;
moved = NO;
zoomed = NO;
}
return;
}
}
else {
// multi-touch
UITouch *touch2 = [[touches allObjects] objectAtIndex:1];
CGFloat finalDistance = [self distanceBetweenTwoPoints:[touch1 locationInView:self]
toPoint:[touch2 locationInView:self]];
CGFloat movement = finalDistance - initialDistance;
NSLog(#"Final Distance: %f, movement=%f",finalDistance,movement);
if (movement != 0) {
CGFloat scale = [self scaleAmount: movement];
self.transform = CGAffineTransformScale(self.transform, scale, scale);
NSLog(#"Scaling: %f", scale);
zoomed = YES;
}
}
}
- (void)singleTap: (NSTimer*)theTimer {
// must override
}
- (void)animateSwipe: (int) direction {
// must override
}
It is not working fine on device. can anyone tell that where i am wrong.
When you use any CGAffinTransform.... the value of the frame property becomes undefined. In your code you are using the frame.size.width and frame.size.height to calculate the change in size. After the first iteration of CGAffinTransformScale you would not get the right scale factor. According to the documentation bounds would be the right property for scale calculations.