Center an UIImageView on the screen when zoom out - iphone

I have an UIImageView inside an UIScrollView. I want that the user can zoom and navigate the image.
This is my work code:
//img is the UIImageView
//scroller is the UIScrollView
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return img;
}
- (void)viewDidLoad {
[super viewDidLoad];
UIImage *image = [UIImage imageNamed:#"map_screen.png"];
img = [[UIImageView alloc] initWithImage:image];
scroller.delegate = self;
scroller.autoresizesSubviews = YES;
scroller.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
scroller.contentSize = img.frame.size;
scroller.scrollEnabled = YES;
scroller.directionalLockEnabled = NO;
scroller.userInteractionEnabled = YES;
CGSize ivsize = img.frame.size;
CGSize ssize = scroller.frame.size;
float scalex = ssize.width / ivsize.width;
float scaley = ssize.height / ivsize.height;
scroller.minimumZoomScale = fmin(1.0, fmax(scaley, scalex));
scroller.zoomScale = fmin(1.0, fmax(scalex, scaley));
[scroller addSubview:img];
img.userInteractionEnabled = YES;
}
all works, but this happened: the minimum zoom is the height of the screen.
My image has the width bigger than the height, so i want that the minumum zoom is the width.
If i write
scroller.minimumZoomScale = fmin(1.0, scalex);
works, but when the user zooms out, the image is not at the center of the screen, but at the top.
i've tried something like this
CGPoint scrollCenter = [scroller center];
[img setCenter:CGPointMake(scrollCenter.x, scrollCenter.y)];
or
img.center = scroller.center;
but with this solution, the image is not completly scrollable, and if i zoom out, it stay again at the top of the screen, but is not completly visible!
What can i do for fix it?

You have to do it manually while the zooming is in progress using the scrollViewDidZoom delegate function... something like
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
// center the image as it becomes smaller than the size of the screen
CGSize boundsSize = scrollView.bounds.size;
CGRect frameToCenter = imageView.frame;
// center horizontally
if (frameToCenter.size.width < boundsSize.width)
{
frameToCenter.origin.x = (boundsSize.width - frameToCenter.size.width) / 2;
} else {
frameToCenter.origin.x = 0;
}
// center vertically
if (frameToCenter.size.height < boundsSize.height)
{
frameToCenter.origin.y = (boundsSize.height - frameToCenter.size.height) / 2;
} else {
frameToCenter.origin.y = 0;
}
imageView.frame = frameToCenter;
}

A Swift 3.0 version of Bastian 's answer, a little more succinct:
func scrollViewDidZoom(_ scrollView: UIScrollView) {
// center the image as it becomes smaller than the size of the screen
let boundsSize = scrollView.bounds.size
var frameToCenter = imageView.frame
// center horizontally and vertically
let widthDiff = boundsSize.width - frameToCenter.size.width
let heightDiff = boundsSize.height - frameToCenter.size.height
frameToCenter.origin.x = (widthDiff > 0) ? widthDiff / 2 : 0;
frameToCenter.origin.y = (heightDiff > 0) ? heightDiff / 2 : 0;
imageView.frame = frameToCenter;
}

Related

Pinch Zoom on Two ImageViews in Single ScrollView on IOS

I am doing a project in which i need two imageviews in single Scrollview with zooming options. UIScrollView allows one view to make zoom easily. But my problem is not like that. I have two imageviews side by side in the scroll view.When I try to zoom the images its not working Is there is any option to zoom two image views at the same time.Please suggest me some idea.
Thanks in advance
Here is code for Zooming two images in single scrollview
I have added two UIImageView's in One UIView and then I have added the UIView to UIScrollView. Following is my code :
- (void)viewDidLoad {
[super viewDidLoad];
self.vwImages = [[UIView alloc]initWithFrame:CGRectMake(0, 0,100,200)];
// 1
UIImage *image = [UIImage imageNamed:#"imgBaskteBall2.jpeg"];
UIImageView *imageView1 = [[UIImageView alloc] initWithImage:image];
imageView1.frame = CGRectMake(0,0,100,100);
[self.vwImages addSubview:imageView1];
UIImage *image2 = [UIImage imageNamed:#"imgBaskteBall1.jpeg"];
UIImageView *imageView2 = [[UIImageView alloc] initWithImage:image2];
imageView2.frame = CGRectMake(0, 100, 100, 100);
[self.vwImages addSubview:imageView2];
// 2
[self.scrollView addSubview:self.vwImages];
self.scrollView.contentSize = self.vwImages.frame.size;
// 3
UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(scrollViewDoubleTapped:)];
doubleTapRecognizer.numberOfTapsRequired = 2;
doubleTapRecognizer.numberOfTouchesRequired = 1;
[self.scrollView addGestureRecognizer:doubleTapRecognizer];
UITapGestureRecognizer *twoFingerTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(scrollViewTwoFingerTapped:)];
twoFingerTapRecognizer.numberOfTapsRequired = 1;
twoFingerTapRecognizer.numberOfTouchesRequired = 2;
[self.scrollView addGestureRecognizer:twoFingerTapRecognizer];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// 4
CGRect scrollViewFrame = self.scrollView.frame;
CGFloat scaleWidth = scrollViewFrame.size.width / self.scrollView.contentSize.width;
CGFloat scaleHeight = scrollViewFrame.size.height / self.scrollView.contentSize.height;
CGFloat minScale = MIN(scaleWidth, scaleHeight);
self.scrollView.minimumZoomScale = minScale;
// 5
self.scrollView.maximumZoomScale = 10.0f;
self.scrollView.zoomScale = minScale;
// 6
[self centerScrollViewContents];
}
- (void)centerScrollViewContents {
CGSize boundsSize = self.scrollView.bounds.size;
CGRect contentsFrame = self.vwImages.frame;
if (contentsFrame.size.width < boundsSize.width) {
contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2.0f;
} else {
contentsFrame.origin.x = 0.0f;
}
if (contentsFrame.size.height < boundsSize.height) {
contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2.0f;
} else {
contentsFrame.origin.y = 0.0f;
}
self.vwImages.frame = contentsFrame;
}
- (void)scrollViewDoubleTapped:(UITapGestureRecognizer*)recognizer {
// 1
CGPoint pointInView = [recognizer locationInView:self.imageView];
// 2
CGFloat newZoomScale = self.scrollView.zoomScale * 1.5f;
newZoomScale = MIN(newZoomScale, self.scrollView.maximumZoomScale);
// 3
CGSize scrollViewSize = self.scrollView.bounds.size;
CGFloat w = scrollViewSize.width / newZoomScale;
CGFloat h = scrollViewSize.height / newZoomScale;
CGFloat x = pointInView.x - (w / 2.0f);
CGFloat y = pointInView.y - (h / 2.0f);
CGRect rectToZoomTo = CGRectMake(x, y, w, h);
// 4
[self.scrollView zoomToRect:rectToZoomTo animated:YES];
}
- (void)scrollViewTwoFingerTapped:(UITapGestureRecognizer*)recognizer {
// Zoom out slightly, capping at the minimum zoom scale specified by the scroll view
CGFloat newZoomScale = self.scrollView.zoomScale / 1.5f;
newZoomScale = MAX(newZoomScale, self.scrollView.minimumZoomScale);
[self.scrollView setZoomScale:newZoomScale animated:YES];
}
- (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView {
// Return the view that you want to zoom
return self.vwImages;
}
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
// The scroll view has zoomed, so you need to re-center the contents
[self centerScrollViewContents];
}
Make object of UIView as container for example viewContainer
[viewContainer addSubView:imageView1];
[viewContainer addSubView:imageView2];
[scrollView addSubView:viewContainer];
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return viewContainer;
}
Add
You can use this
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return [self.scrollView.subviews objectAtIndex:0];
}
the viewForZoomingInScrollView delegate method return the object at Index 0.
From Properly zooming a UIScrollView that contains many subviews
add both the imageView in the view and replace this method
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return view;
}

crop a zoomed image in ImageView inside scrollView

I already do Lot of efforts from my Side. finally I need help. thanks
Goal :
1) How I fit imageView inside ScrollView
2) How I crop a zoomed Image in inside scrollView.
I have a imageView inside Scroll View. I wants crop image after zoomed which is display inside scrollview boundary. I cropped image already but it not exactly same which i wants.
Here I set backgroundColor Black to my scrollView. And when I place imageView inside it, it's not fit.
after zoom image inside scroll view is
and after crop image is
and my code is here :
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect frame1 = CGRectMake(50,50,200,200);
CGRect frame2 = CGRectMake(50,50,200,200);
imageView1=[[UIImageView alloc]initWithFrame:frame1];
imageView1.image= [UIImage imageNamed:#"back.jpeg"];
imageView1.backgroundColor=[UIColor brownColor];
imageView1.contentMode = UIViewContentModeScaleAspectFit;
scroll=[[UIScrollView alloc]initWithFrame:frame2];
scroll.backgroundColor=[UIColor blackColor];
[scroll addSubview:imageView1];
scroll.delegate=self;
[self.view addSubview:scroll];
[self setContentSizeForScrollView];
self.imageView1.userInteractionEnabled = YES;
}
setting scroll view contentSize
-(void)setContentSizeForScrollView
{
// scroll.contentSize = CGSizeMake(imageView1.frame.size.width,imageView1.frame.size.height);
scroll.contentSize = CGSizeMake(200, 200);
scroll.minimumZoomScale = .50;
scroll.maximumZoomScale = 1.5;
}
and my crop logic is
-(IBAction)cropButtonClicked
{
//Calculate the required area from the scrollview
CGRect rect = CGRectMake(50, 50, 200,200);
UIImage *image = [self imageByCropping:imageView1.image toRect:rect];
imageView1.image=image;
imageView1.contentMode = UIViewContentModeScaleAspectFit;
}
And this method crop image :
- (UIImage*)imageByCropping:(UIImage *)myImage toRect:(CGRect)cropToArea{
CGImageRef cropImageRef = CGImageCreateWithImageInRect(myImage.CGImage, cropToArea);
UIImage* cropped = [UIImage imageWithCGImage:cropImageRef];
CGImageRelease(cropImageRef);
return cropped;
}
Answer of my own Question : After many efforts i found the answer of both of my questions.
and it work good for me. I share here, may be it help someone. :)
1) Fit image View inside Scroll View. I use this link
- (void)centerScrollViewContents {
CGSize boundsSize = scroll.bounds.size;
CGRect contentsFrame = self.imageView1.frame;
if (contentsFrame.size.width < boundsSize.width) {
contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2.0f;
}
else {
contentsFrame.origin.x = 0.0f;
}
if (contentsFrame.size.height < boundsSize.height) {
contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2.0f;
}
else {
contentsFrame.origin.y = 0.0f;
}
self.imageView1.frame = contentsFrame;
}
2) Crop a zoomed Image in inside scrollView. I use this link
UIGraphicsBeginImageContext(CGSizeMake(200, 200));
[scroll.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *fullScreenshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
imageView1.contentMode = UIViewContentModeScaleAspectFill;
UIImageWriteToSavedPhotosAlbum(fullScreenshot, nil, nil, nil);
return fullScreenshot;
I had a similar problem recently, I got the solution using the relative idea ( Xa,b = Xa,c - Xb,c )
-(IBAction)crop:(id)sender{
// F = frame
// i = image
// iv = imageview
// sv = self.view
// of = offset
//Frame Image in imageView coordinates
CGRect Fi_iv = [self frameForImage:self.image inImageViewAspectFit:self.imageView];
//Frame ImageView in self.view coordinates
CGRect Fiv_sv = self.imageView.frame;
//Frame Image in self.view coordinates
CGRect Fi_sv = CGRectMake(Fi_iv.origin.x + Fiv_sv.origin.x
,Fi_iv.origin.y + Fiv_sv.origin.y,
Fi_iv.size.width, Fi_iv.size.height);
//ScrollView offset
CGPoint offset = self.scrollView.contentOffset;
//Frame Image in offset coordinates
CGRect Fi_of = CGRectMake(Fi_sv.origin.x - offset.x,
Fi_sv.origin.y - offset.y,
Fi_sv.size.width,
Fi_sv.size.height);
CGFloat scale = self.imageView.image.size.width/Fi_of.size.width;
//the crop frame in image offset coordinates
CGRect Fcrop_iof = CGRectMake((self.cropView.frame.origin.x - Fi_of.origin.x)*scale,
(self.cropView.frame.origin.y - Fi_of.origin.y)*scale,
self.cropView.frame.size.width*scale,
self.cropView.frame.size.height*scale);
UIImage *image = [self image:self.imageView.image cropRect:Fcrop_iof];
// Use this crop image...
You can crop the image using:
//Use this code to crop when you have the right frame
-(UIImage*)image:(UIImage *)image cropRect:(CGRect)frame
{
// Create a new UIImage
CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, frame);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return croppedImage;
}
Since you are using the ImageView in Aspect Fit, you need to calculate the image frame inside the imageView
-(CGRect)frameForImage:(UIImage*)image inImageViewAspectFit:(UIImageView*)imageView
{
float imageRatio = image.size.width / image.size.height;
float viewRatio = imageView.frame.size.width / imageView.frame.size.height;
if(imageRatio < viewRatio)
{
float scale = imageView.frame.size.height / image.size.height;
float width = scale * image.size.width;
float topLeftX = (imageView.frame.size.width - width) * 0.5;
return CGRectMake(topLeftX, 0, width, imageView.frame.size.height);
}
else
{
float scale = imageView.frame.size.width / image.size.width;
float height = scale * image.size.height;
float topLeftY = (imageView.frame.size.height - height) * 0.5;
return CGRectMake(0, topLeftY, imageView.frame.size.width, height);
}
}
I hope this code can work for you as it worked for me.
Best,
Rafael.

UIScrollView Zooming Crashes App with Exc_Bad_Access

I am getting a Exc_Bad_Access error in main when I try to scroll my UIScrollView. This program is simple. I have A UIViewController added in AppDelegate. Then, here is the code in the ViewController. This works fine for scrolling but as soon as I add tmpScrollView.delegate = self. The program won't scroll or zoom and gives me the Exc_Bad_Access error when I try to zoom.
#interface MainViewController : UIViewController &ltUIScrollViewDelegate>
#property (nonatomic,retain) UIScrollView *tmpScrollView;
#property (nonatomic,retain) UIView *containerView;
#end
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
tmpScrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
tmpScrollView.delegate = self;
[self.view addSubview:tmpScrollView];
// Set up the container view to hold our custom view hierarchy
CGSize containerSize = CGSizeMake(640.0f, 640.0f);
self.containerView = [[UIView alloc] initWithFrame:(CGRect){.origin=CGPointMake(0.0f, 0.0f), .size=containerSize}];
[self.tmpScrollView addSubview:self.containerView];
// Set up custom view hierarchy
UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 640.0f, 80.0f)];
redView.backgroundColor = [UIColor redColor];
[self.containerView addSubview:redView];
UIView *blueView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 560.0f, 640.0f, 80.0f)];
blueView.backgroundColor = [UIColor blueColor];
[self.containerView addSubview:blueView];
UIView *greenView = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 160.0f, 320.0f, 320.0f)];
greenView.backgroundColor = [UIColor greenColor];
[self.containerView addSubview:greenView];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"slow.png"]];
imageView.center = CGPointMake(320.0f, 320.0f);
[self.containerView addSubview:imageView];
//Tell the scroll view the size of the contents
self.tmpScrollView.contentSize = containerSize;
}
-(void)viewWillAppear:(BOOL)animated
{
NSLog(#"Will Appear");
[super viewWillAppear:animated];
// Set up the minimum & maximum zoom scales
CGRect scrollViewFrame = self.tmpScrollView.frame;
CGFloat scaleWidth = scrollViewFrame.size.width / self.tmpScrollView.contentSize.width;
CGFloat scaleHeight = scrollViewFrame.size.height / self.tmpScrollView.contentSize.height;
CGFloat minScale = MIN(scaleWidth, scaleHeight);
self.tmpScrollView.minimumZoomScale = minScale;
self.tmpScrollView.maximumZoomScale = 1.0f;
self.tmpScrollView.zoomScale = minScale;
//***** Here is the line for setting the delegate
self.tmpScrollView.delegate = self;
[self centerScrollViewContents];
}
-(void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{
NSLog(#"End Zoom");
}
-(UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView {
// Return the view that we want to zoom
return self.containerView;
}
-(void)scrollViewDidZoom:(UIScrollView *)scrollView {
// The scroll view has zoomed, so we need to re-center the contents
[self centerScrollViewContents];
}
#end
Thanks for any help. This has been driving me crazy for a day now...
Edit: Adding centerScrollViewContens too:
- (void)centerScrollViewContents {
CGSize boundsSize = self.tmpScrollView.bounds.size;
CGRect contentsFrame = self.containerView.frame;
if (contentsFrame.size.width < boundsSize.width) {
contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2.0f;
} else {
contentsFrame.origin.x = 0.0f;
}
if (contentsFrame.size.height < boundsSize.height) {
contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2.0f;
} else {
contentsFrame.origin.y = 0.0f;
}
self.containerView.frame = contentsFrame;
}
Whatever Code you have provided is working fine on my end.May be there could be some sort of problem in your "centerScrollViewContents" method.Can you post the code for this method also???
You need to work out the minimum zoom scale for the scroll view. A zoom scale of one means that the content is displayed at normal size. A zoom scale below one shows the content zoomed out, while a zoom scale of greater than one shows the content zoomed in. To get the minimum zoom scale, you calculate how far you’d need to zoom out so that the image fits snugly in your scroll view’s bounds based on its width. Then you do the same based upon the image’s height. The minimum of those two resulting zoom scales will be the scroll view’s minimum zoom scale. That gives you a zoom scale where you can see the entire image when fully zoomed out.
Swift:
let scrollViewFrame = scrollView.frame
let scaleWidth = scrollViewFrame.size.width / scrollView.contentSize.width
let scaleHeight = scrollViewFrame.size.height / scrollView.contentSize.height
let minScale = min(scaleWidth, scaleHeight);
scrollView.minimumZoomScale = minScale;
Objective-C
CGFloat scrollViewFrame = scrollView.frame
CGFloat scaleWidth = scrollViewFrame.size.width / scrollView.contentSize.width
CGFloat scaleHeight = scrollViewFrame.size.height / scrollView.contentSize.height
CGFloat minScale = min(scaleWidth, scaleHeight);
scrollView.minimumZoomScale = minScale;
From other projects and personal experience doing heavy GPU on the iOS (endless scroll, maximum bitmap size, etc), I've noticed that each device has it's own threshold. For past projects, I've also hardcoded the below values as the minimumZoomScale to prevent the crashes:
scale :
{
iPad : {
min : 0.8
, max : 1.6
}
, iPhone : {
min : 0.25
, max : 1.6
}
, iPhone6 : {
min : 0.3333
, max : 1.6
}
, iPhoneResizable: {
min : 1
, max : 1.6
}
}
Great tutorial for beginners: http://www.raywenderlich.com/76436/use-uiscrollview-scroll-zoom-content-swift

How to center image in a uiimageview/uiscrollview (pre and post zooming)

I am trying to center an image (with respect to the iphone screen) such that when the view is loaded the image is center width/height... In my case my view is loaded at pixel points 0,0 of the image itself and if I zoom out the image appears in the top left corner as opposed to mid-center of the screen/view. Here is what I have so far:
UIImage *image = [UIImage imageNamed: #"t.bmp"];
self.view.backgroundColor = [UIColor blackColor];
self.mi.frame = CGRectMake(0, 0, image.size.width, image.size.height);
self.mi.contentMode = (UIViewContentModeCenter);
self.mi.backgroundColor = [UIColor blackColor];
[self.mi setImage:image];
/* Draw a line here!!
UIGraphicsBeginImageContext(self.mi.frame.size);
[self.mi.image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGContextSetLineWidth(context, 20.0);
CGContextBeginPath(context);
CGContextMoveToPoint(context, 0,0);
CGContextAddLineToPoint(context, 200, 200);
CGContextMoveToPoint(context, 200,0);
CGContextAddLineToPoint(context, 0, 200);
CGContextStrokePath(context);
self.mi.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
*/
self.expimg.maximumZoomScale = 2.0;
self.expimg.minimumZoomScale = 0.1;
self.expimg.clipsToBounds = YES;
self.expimg.delegate = self;
[self.expimg setContentSize:self.mi.frame.size];
[self.expimg addSubview: self.mi];
[self.view addSubview: self.expimg];
Thanks!
Edit: mi is a UIImageView and expimg is a UIScrollView (used interface builder). Also, viewForZoomingInScrollView is defined.
You should be able to do this by adjusting the position and size of the image and scroll view on initial load, and as zoom levels change. Make a method that is called on viewDidLoad, and again on the UIScrollViewDelegate method scrollViewDidZoom:.
Something like this should work (where imageView and scrollView are class attributes):
- (void)centerImage {
CGSize screenSize = CGSizeMake(320, 480);
CGSize imageSize = imageView.frame.size;
imageSize.width = imageSize.width * scrollView.zoomScale;
imageSize.height = imageSize.height * scrollView.zoomScale;
CGSize scrollSize = scrollView.frame.size;
CGFloat centerX;
CGFloat centerY;
CGFloat left;
CGFloat top;
if (imageSize.width > screenSize.width) {
scrollSize.width = imageSize.width;
centerX = imageSize.width/2;
left = 0;
} else {
scrollSize.width = screenSize.width;
centerX = screenSize.width/2;
left = centerX - imageSize.width/2;
}
if (imageSize.height > screenSize.height) {
scrollSize.height = imageSize.height;
centerY = imageSize.height/2;
top = 0;
} else {
scrollSize.height = screenSize.height;
centerY = screenSize.width/2;
top = centerY - imageSize.height/2;
}
CGRect scrollFrame = scrollView.frame;
scrollFrame.size = scrollSize;
scrollView.frame = scrollFrame;
CGRect imageFrame = imageView.frame;
imageFrame.origin = CGPointMake(left, top);
scrollView.contentOffset = CGPointMake(centerX-(imageSize.width/2), centerY-(imageSize.height/2));
}
I have not tested this, so some of my math could be wrong. Either way, it will hopefully give you a good idea of what to do.
Step 1: You create an image view property then init it at viewDidLoad and add to scrollView:
self.pictureImage = [[UIImageView alloc]initWithImage:self.picture];
[_scrollView addSubview:_pictureImage];
self.pictureImage.alpha = 0;
_scrollView.delegate = self;
Step 2: Create adjustZoomScale function to get minimum scale
- (CGFloat)adjustZoomScale{
CGFloat scale = self.scrollView.bounds.size.width / self.pictureImage.bounds.size.width;
CGFloat h = scale * self.pictureImage.bounds.size.height;
if (h > self.scrollView.bounds.size.height) {
scale = self.scrollView.bounds.size.height / self.pictureImage.bounds.size.height;
}
return scale;
}
Step 3: Because frame of scroll view will be updated at viewDidAppear so we need to adjust zoom scale here. And set alpha to make image appear smoother:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear: animated];
_scrollView.maximumZoomScale = 1.0;
_scrollView.minimumZoomScale = [self adjustZoomScale];
[_scrollView setZoomScale:_scrollView.minimumZoomScale];
self.pictureImage.alpha = 1;
}
Step 4: Implement viewForZoomingInScrollView (scroll delegate method) and return image view
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
return self.pictureImage;
}
Step 5: Implement scrollViewDidZoom (scroll delegate method) and adjust point for image view
- (void)scrollViewDidZoom: (UIScrollView*) scrollView {
CGSize boundsSize = scrollView.bounds.size;
CGRect contentsFrame = _pictureImage.frame;
if (contentsFrame.size.width < boundsSize.width) {
contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2.0;
} else {
contentsFrame.origin.x = 0.0;
}
if (contentsFrame.size.height < boundsSize.height) {
contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2.0;
} else {
contentsFrame.origin.y = 0.0;
}
_pictureImage.frame = contentsFrame;
}
Thank shawhu at this post for point adjusting for image view while zooming
[scrollView zoomToRect:CGRectMake(x, y, width, height) animated:YES]; will work for you...
Where rect should have those center coordinates as origin.

How to Zoom out an image with keeping it in a center of the Scrollview

In my application i need to capture an image with cam and then pass it to the imageView, which is used as a subView for a ScrollView.
The requirement is "the image must facilitate 1/4th size for zoom out and 3 times the size for zoom in".
Now the problem is that when i zoom out this image the image zooms out, but it doesn't hold its position in the center. it sets its position respective to the touches of finger.
(No double tap zooming is there, and not required too)
Below is the code..,
- (void)viewDidLoad
{
[super viewDidLoad];
UIImage* tmpImage = nil;
tmpImage = [roomImage resizedImage:imageScrollView.frame.size interpolationQuality:0];
imageView = [[UIImageView alloc] initWithImage:tmpImage];
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageScrollView.delegate = self;
imageScrollView.canCancelContentTouches = NO;
imageScrollView.minimumZoomScale = 0.25;
imageScrollView.maximumZoomScale = 3.00;
imageScrollView.clipsToBounds = YES;
[imageView sizeToFit];
[imageScrollView addSubview:imageView];
imageScrollView.contentSize = imageView.frame.size;
imageScrollView.contentMode = UIViewContentModeScaleAspectFit;
imageScrollView.contentOffset = CGPointMake(imageScrollView.frame.size.width/2, imageScrollView.frame.size.height/2);
imageScrollView.autoresizesSubviews = YES;
imageScrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
CGFloat f,x,y;
if(tmpImage.size.height > tmpImage.size.width)
{
f = (imageScrollView.frame.size.height/tmpImage.size.height);
}
else
{
f = (imageScrollView.frame.size.width/tmpImage.size.width);
}
x = (imageScrollView.frame.size.width - tmpImage.size.width*f)/2;
y = (imageScrollView.frame.size.height - tmpImage.size.height*f)/2;
imageView.bounds = CGRectMake(x, y,tmpImage.size.width, tmpImage.size.height);
[imageView setNeedsDisplay];
[imageScrollView setZoomScale:f animated:YES];
[imageScrollView setNeedsDisplay];
jpgPath = nil;
[roomImage release];
roomImage = nil;
}
Hope any one can help me out..,
Thanks in advance..,
If I'm understanding you correctly you could subclass the UIScrollView and have something like the following in the layoutSubviews method to keep it's contents centred:
-(void)layoutSubviews {
[super layoutSubviews];
CGSize boundsSize = self.bounds.size;
CGRect contentViewFrame = contentView.frame;
if (contentViewFrame.size.width < boundsSize.width) {
contentViewFrame.origin.x = (boundsSize.width - contentViewFrame.size.width) / 2;
} else {
contentViewFrame.origin.x = 0;
}
if (contentViewFrame.size.height < boundsSize.height) {
contentViewFrame.origin.y = (boundsSize.height - contentViewFrame.size.height) / 2;
} else {
contentViewFrame.origin.y = 0;
}
contentView.frame = contentViewFrame;
}
The contentView variable is an iVar which represents in you case the imageView you want inside the scrollView. Hope this helps :-)