Thursday, February 10, 2011

Iphone Tutorial: UIImage With Zooming And Tapping And Rotation

In this tutorial I’m going to explain a common task for iphone and ipad apps, which is simply how to put have a zoomable image inside your application with taping abilities.

The steps described here works both for iphone and for ipad apps. This is how the final application will look like:



Step 1: Application setup

Open xcode and create a view based application. Name the project ImageZooming



Now we need to do two things. First, we need to import our image which you can find here, then we need to import a class provided by apple two implement zooming by tapping.

To import the image, save it on your hard disk and then drag it to your xcode project window under the resources folder. Name the image image1.jpg. Make sure to check the “Copy items to destination group’s folder if needed”:



Do the same with the apple class files that you can download from here, but drop them in the classes folder this time.

Step 2: Writing the code

In order to make our image zoomable, we need to embed it into a UIScrollView. We can use Interface Builder to instantiate the scroll View and then go back to Xcode for the rest.

Open Interface Builder by double clicking on MainWindow.xib inside the Resources folder. Drag an instance of UIScrollView from the Library (press Command + Shift + L if it’s not visible) to the main view, and resize it to fit all the window.



Make sure that the scroll view is selected and click on the size attributes panel (or press command + 3). Make sure that autoresizing is enabled in all directions (which it is by default) so that the scroll view will fill the entire screen when we rotate the device.

Now we can go back to xcode and write our code. Open the file ImageZoomingViewController.h and declare the following instance variables:

view plaincopy to clipboardprint?
#import

@interface ImageZoomingViewController : UIViewController

@property (nonatomic, retain) IBOutlet UIScrollView *scrollView;
@property (nonatomic, retain) UIImageView *image;

@end
Note that if you use snow leopard you can just declare the properties like I’ve done here. We will connect the scrollView later, but for now let’s head to the implementation file. Here’s how the code should look like:

view plaincopy to clipboardprint?
#import "ImageZoomingViewController.h"
#import "TapDetectingImageView.h"

#define ZOOM_STEP 1.5


@interface ImageZoomingViewController (UtilityMethods)
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center;
@end

@implementation ImageZoomingViewController

@synthesize imageScrollView, imageView;

- (void)viewDidLoad {
[super viewDidLoad];

imageScrollView.bouncesZoom = YES;
imageScrollView.delegate = self;
imageScrollView.clipsToBounds = YES;

imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"image1.jpg"]];
imageView.userInteractionEnabled = YES;
imageView.autoresizingMask = ( UIViewAutoresizingFlexibleWidth );
[imageScrollView addSubview:imageView];

imageScrollView.contentSize = [imageView frame].size;

// add gesture recognizers to the image view
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
UITapGestureRecognizer *twoFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerTap:)];

[doubleTap setNumberOfTapsRequired:2];
[twoFingerTap setNumberOfTouchesRequired:2];

[imageView addGestureRecognizer:singleTap];
[imageView addGestureRecognizer:doubleTap];
[imageView addGestureRecognizer:twoFingerTap];

[singleTap release];
[doubleTap release];
[twoFingerTap release];

// calculate minimum scale to perfectly fit image width, and begin at that scale
float minimumScale = [imageScrollView frame].size.width / [imageView frame].size.width;
//imageScrollView.maximumZoomScale = 1.0;
imageScrollView.minimumZoomScale = minimumScale;
imageScrollView.zoomScale = minimumScale;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return YES;
}


- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];

// Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
self.imageScrollView = nil;
self.imageView = nil;
}

#pragma mark UIScrollViewDelegate methods

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return imageView;
}

#pragma mark TapDetectingImageViewDelegate methods

- (void)handleSingleTap:(UIGestureRecognizer *)gestureRecognizer {
// single tap does nothing for now
}

- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer {
// zoom in
float newScale = [imageScrollView zoomScale] * ZOOM_STEP;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
[imageScrollView zoomToRect:zoomRect animated:YES];
}

- (void)handleTwoFingerTap:(UIGestureRecognizer *)gestureRecognizer {
// two-finger tap zooms out
float newScale = [imageScrollView zoomScale] / ZOOM_STEP;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
[imageScrollView zoomToRect:zoomRect animated:YES];
}

#pragma mark Utility methods

- (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 = [imageScrollView frame].size.height / scale;
zoomRect.size.width = [imageScrollView 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);

return zoomRect;
}

@end
First, we import the zooming class provided by Apple and synthesize our instance variables, then we instantiate our image and we add it to the scroll view. We need to set some options like userInteractionEnabled to make it work. The other code is provided by apple and should be easy to understand.

The last thing we need to do is connect our scroll view to the view. To do so, go back to xcode (save first), and select the imageZoomingViewController object:



Now choose the connection panel (or press command + 2) and connect the imageScrollView variable to the scroll view that you dragged before. Save Interface Builder, go back to Xcode. Build and run.

You can download the application source code from here.

You should subscribe to the RSS Feed Here.

No comments:

Post a Comment