UIScroll view for comic App - cocoa-touch

I´m working on an ipad app for a comic but i can´t get my scroll view to work. I need it to do:
Pinch zoom
Rotation
Double tap and move by comic strip
Here´s an example of what i want to get http://vimeo.com/16073699 (Second 35 +-)
Right now i have pinch zoom but i can get the scroll view to rotate and center image.
Here´s my controller code:
#define ZOOM_VIEW_TAG 100
#define ZOOM_STEP 2
#define PAGE_TIME 10
- (void)viewDidLoad{
[super loadView];
self.myImage.image = [UIImage imageNamed:#"Tira01.jpg"];
[self.myImage setTag:ZOOM_VIEW_TAG];
UISwipeGestureRecognizer *recognizer;
recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(Tap)];
[(UITapGestureRecognizer *)recognizer setNumberOfTouchesRequired:1];
[(UITapGestureRecognizer *)drecognizer setNumberOfTapsRequired:1];
[[self myImage] addGestureRecognizer:recognizer];
[recognizer release];
self.drecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleTap:)];
[(UITapGestureRecognizer *)drecognizer setNumberOfTouchesRequired:1];
[(UITapGestureRecognizer *)drecognizer setNumberOfTapsRequired:2];
[[self myImage] addGestureRecognizer:drecognizer];
[drecognizer release];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return [myScrollView viewWithTag:ZOOM_VIEW_TAG];
}
- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer {
UIInterfaceOrientation currentOrientation = [[UIDevice currentDevice] orientation];
if(!self.zoomed)
{
// double tap zooms in
float newScale = [self.myScrollView zoomScale] * ZOOM_STEP;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
[self.myScrollView zoomToRect:zoomRect animated:YES];
self.zoomed = YES;
}
else {
float newScale = [self.myScrollView zoomScale] / ZOOM_STEP;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
[self.myScrollView zoomToRect:zoomRect animated:YES];
self.zoomed = NO;
}
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
return YES;
}
- (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.myScrollView frame].size.height / scale;
zoomRect.size.width = [self.myScrollView 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;
}
In interface builder i have:
-> UIView(ScaleToFill mode)
--> UIScrollView (ScaleToFill mode)
---> UIImageView (AspectFit mode)
I don´t know what i´m doing wrong but i´m going crazy with that :(

Regarding the UIScrollView centering the content, I might be wrong here, but the UIScrollView doesn't automatically do that.
In my app i'm manually doing it by actually moving the content in the scrollView so that it is centered.
Just as a quick explanation for the code below, if the content (image) frame is smaller than the bounds of the scroll view, then adjust the position of the content horizontally and vertically.
The code below is from my class derived from UIScrollView. If you're using the default UIScrollView, you can use this code in the parent UIView.
- (void)layoutSubviews
{
[super layoutSubviews];
if (![self centersContent])
{
return;
}
// center the image as it becomes smaller than the size of the screen
CGSize boundsSize = self.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;
}

Related

How to display animated GIF in Objective C on top of the layered View?

I am trying to draw animated gif on my screen in mac OSX app .
I used this code to insert the gif: I can see the Gif as 1 picture it doesn't animates
only static picture :( what should I add to make it animated ?
#import <Cocoa/Cocoa.h>
#import <Quartz/Quartz.h>//for drawing circle
#import "sharedPrefferences.h"
#interface GenericFanSubView : NSView
{
NSColor * _backgroundColor;
NSImageView* imageView;
}
- (void)setBackgroundColor :(NSColor*)color;
- (void)insertGif1;
- (void)insertGif2;
- (void)insertGif3;
#end
#import "GenericFanSubView.h"
#define PI 3.14285714285714
#implementation GenericFanSubView
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
imageView = [[NSImageView alloc]initWithFrame:CGRectMake(0, 0,self.frame.size.width,self.frame.size.height)];
[imageView setAnimates: YES];
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
[super drawRect:dirtyRect];
// Drawing code here.
[self drawCircleInRect];
_backgroundColor = [NSColor whiteColor];
[self insertGif1];
}
-(void)drawCircleInRect
{
//draw colored circle here
CGContextRef context = [[NSGraphicsContext // 1
currentContext] graphicsPort];
// ********** Your drawing code here ********** // 2
CGContextSetFillColorWithColor(context,[self NSColorToCGColor:(_backgroundColor)]);
float radius1 = self.frame.size.height/2;
float startAngle = 0;
float endAngle = endAngle = PI*2;
CGPoint position = CGPointMake(self.frame.size.height/2,self.frame.size.height/2);//center of the view
CGContextBeginPath(context);
CGContextAddArc(context, position.x, position.y, radius1, startAngle, endAngle, 1);
CGContextDrawPath(context, kCGPathFill); // Or kCGPathFill
}
- (void)setBackgroundColor :(NSColor*)color
{
_backgroundColor = color;
[self setNeedsDisplay:YES];
}
- (CGColorRef)NSColorToCGColor:(NSColor *)color
{
NSInteger numberOfComponents = [color numberOfComponents];
CGFloat components[numberOfComponents];
CGColorSpaceRef colorSpace = [[color colorSpace] CGColorSpace];
[color getComponents:(CGFloat *)&components];
CGColorRef cgColor = CGColorCreate(colorSpace, components);
return cgColor;
}
//curentlly calling only this 1
- (void)insertGif1
{
[imageView removeFromSuperview];
[imageView setImageScaling:NSImageScaleNone];
[imageView setAnimates: YES];
imageView.image = [NSImage imageNamed:#"FanBlades11.gif"];
[self addSubview:imageView];
}
#end
Edit: I discovered the source of the problem:
I was adding my class (that represents gif inside the circle) on top of RMBlurredView
and the animations doesn't work when I adding it as subview ,However it works on all the other views I added.
Any ideas what could be the reason inside the RMBlurredView to stop my NSImageView from animating ?
Edit:
I think [self setWantsLayer:YES]; is the reason I am not getting animations
how can I still get the animation with this feature enabled?
Edit:
Here is a simple sample with my problem
http://snk.to/f-cdk3wmfn
my gif:This is my gif it is invisible on white background color
"You must disable the autoscaling feature of the NSImageView for the
animation playback to function. After you've done that, no extra
programming required. It works like a charm!"
--http://www.cocoabuilder.com/archive/cocoa/108530-nsimageview-and-animated-gifs.html
imageView.imageScaling = NSImageScaleNone;
imageView.animates = YES;
needed for layer backed views:
if the image view is in a layer backed view or is layer backed itself:
imageView.canDrawSubviewsIntoLayer = YES;
working example using the question's own gif:
NSImageView *view = [[NSImageView alloc] initWithFrame:CGRectMake(10, 10, 50, 50)];
view.imageScaling = NSImageScaleNone;
view.animates = YES;
view.image = [NSImage imageNamed:#"FanBlades2_42x42.gif"];
view.canDrawSubviewsIntoLayer = YES;
NSView *layerview = [[NSView alloc] initWithFrame:CGRectMake(0, 0, 60, 60)];
layerview.wantsLayer = YES;
[layerview addSubview:view];
[self.window.contentView addSubview:layerview];

Multiple images/buttons staying relative to their position on a zoomable image

I've made a map with UIScrolView, I want to place other small images or buttons onto the map and have them be in a relative position on the map when you zoom in and be able to click on them whenever. So when zoomed out, a button on country A, will still be on Country A when zoomed in, and disappear out of the screen when you scroll out of the countries view whilst zoomed in. How could I go about doing this?
As i can understand, you want to place custom views on your own custom map. And you need to keep the same sizes for views, but they should move when you scroll or zoom imageView.
You have to place views to scrollView's superview and recalculate positions when you zoom or scroll:
CustomMapViewController.h:
#interface CustomMapViewController : UIViewController <UIScrollViewDelegate>
{
UIScrollView *_scrollView;
UIImageView *_mapImageView;
NSArray *_customViews;
}
CustomMapViewController.m:
#import "CustomMapViewController.h"
enum {
kAddContactButton = 1,
kInfoDarkButton,
kInfoLightButton,
kLogoImage,
};
#implementation CustomMapViewController
- (void)dealloc
{
[_scrollView release]; _scrollView = nil;
[_mapImageView release]; _mapImageView = nil;
[_customViews release]; _customViews = nil;
[super dealloc];
}
- (void) loadView
{
[super loadView];
UIImageView *mapImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"map.png"]];
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
scrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
scrollView.delegate = self;
scrollView.minimumZoomScale = 0.2;
scrollView.maximumZoomScale = 2.0;
[scrollView addSubview:mapImageView];
scrollView.contentSize = mapImageView.frame.size;
[self.view addSubview:scrollView];
_scrollView = scrollView;
_mapImageView = mapImageView;
// Add custom views
UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeContactAdd];
btn1.tag = kAddContactButton;
[self.view addSubview:btn1];
UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeInfoDark];
btn2.tag = kInfoDarkButton;
[self.view addSubview:btn2];
UIButton *btn3 = [UIButton buttonWithType:UIButtonTypeInfoLight];
btn3.tag = kInfoLightButton;
[self.view addSubview:btn3];
UIImageView *image = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"logo.png"]] autorelease];
image.tag = kLogoImage;
[self.view addSubview:image];
_customViews = [[NSArray alloc] initWithObjects:btn1, btn2, btn3, image, nil];
[self _zoomToFit];
}
- (void) _zoomToFit
{
UIScrollView *scrollView = _scrollView;
CGFloat contentWidth = scrollView.contentSize.width;
CGFloat contentHeigth = scrollView.contentSize.height;
CGFloat viewWidth = scrollView.frame.size.width;
CGFloat viewHeight = scrollView.frame.size.height;
CGFloat width = viewWidth / contentWidth;
CGFloat heigth = viewHeight / contentHeigth;
CGFloat scale = MIN(width, heigth); // to fit
// CGFloat scale = MAX(width, heigth); // to fill
// May be should add something like this
if ( scale < _scrollView.minimumZoomScale ) {
_scrollView.minimumZoomScale = scale;
} else if ( scale > _scrollView.maximumZoomScale ) {
_scrollView.maximumZoomScale = scale;
}
_scrollView.zoomScale = scale;
}
////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - Positions
- (void) _updatePositionForViews:(NSArray *)views
{
CGFloat scale = _scrollView.zoomScale;
CGPoint contentOffset = _scrollView.contentOffset;
for ( UIView *view in views ) {
CGPoint basePosition = [self _basePositionForView:view];
[self _updatePositionForView:view scale:scale basePosition:basePosition offset:contentOffset];
}
}
- (CGPoint) _basePositionForView:(UIView *)view
{
switch (view.tag) {
case kAddContactButton:
return CGPointMake(50.0, 50.0);
case kInfoDarkButton:
return CGPointMake(250.0, 250.0);
case kInfoLightButton:
return CGPointMake(450.0, 250.0);
case kLogoImage:
return CGPointMake(650.0, 450.0);
default:
return CGPointZero;
}
}
- (void) _updatePositionForView:(UIView *)view scale:(CGFloat)scale basePosition:(CGPoint)basePosition offset:(CGPoint)offset;
{
CGPoint position;
position.x = (basePosition.x * scale) - offset.x;
position.y = (basePosition.y * scale) - offset.y;
CGRect frame = view.frame;
frame.origin = position;
view.frame = frame;
}
//////////////////////////////////////////////////////////////////////////////////////
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
[self _updatePositionForViews:_customViews];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[self _updatePositionForViews:_customViews];
}
- (UIView *) viewForZoomingInScrollView:(UIScrollView *)scrollView;
{
return _mapImageView;
}
#end

How to put a picture below navigationController?

I want to build an iPhone app for my band.
I wondered how to put a picture below the navigationController, which is visible only on pulling down (let's have a glance to this app) :
http://img11.hostingpics.net/pics/227613image.jpg
Thank a lot.
use scrollview method
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGPoint offset = scrollView.contentOffset;
CGRect bounds = scrollView.bounds;
CGSize size = scrollView.contentSize;
UIEdgeInsets inset = scrollView.contentInset;
float y = offset.y + bounds.size.height - inset.bottom;
float h = size.height;
if(scrollView.contentOffset.y < 0.0f && scrollView.contentOffset.y > -80.0f)
{
//
display your image at this point
NSLog(#"\n pos: %f of %f", y, h);
}
You can do it much easier:
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0,0,320,1000)];
[self.view addSubview:scrollView];
This will add a scrollView :)
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,HEIGHTYOUWANT)];
imgView.image = [UIImage imageName:#"band.png"];
[scrollView addSubview:imgView];
This will add a picture of your Band, which has to be in your Projectfolder at the top of the scrollView, so if you scroll down, the picture goes with it :)
CREATE A UINAVIGATIONBAR HERE
[self.view addSubview:navigationBar];
//^ it has to be self.view not scrollView otherwise the navigationbar moves too

loading screen not centered on second launch

I have a UIView which is my loading view. All it does is display the circular loading circle(lol to much "circle" for one sentence).
It works fine the first time but after that the circle is not centered. It moves to the left and down some. How can I get it to always be centered, take in mind I have limited the app to only display in the landscape modes (landscape left, landscape right) in all views so the issue is not coming from the device being rotated.
call to load the view:
loadingViewController = [LoadingViewController loadSpinnerIntoView:self.view];
LoadingViewController.h:
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import "CrestronClient.h"
#interface LoadingViewController : UIView
{
CrestronClient *cClient;
}
+(LoadingViewController *)loadSpinnerIntoView:(UIView *)superView;
-(void)removeLoadingView;
- (UIImage *)addBackground;
#end
LoadingView.m:
#import "LoadingViewController.h"
#import "RootViewController.h"
#implementation LoadingViewController
CGRect priorFrameSettings;
UIView *parentView;
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||interfaceOrientation == UIInterfaceOrientationLandscapeRight ) {
return YES;
}else{
return NO;
}
}
-(void)removeLoadingView
{
// [parentView setFrame:priorFrameSettings];
CATransition *animation = [CATransition animation];
[animation setType:kCATransitionFade];
[[[self superview] layer] addAnimation:animation forKey:#"layerAnimation"];
[self removeFromSuperview];
}
+(LoadingViewController *)loadSpinnerIntoView:(UIView *)superView
{
priorFrameSettings = superView.frame;
parentView = superView;
// [superView setFrame:CGRectMake(0, 0, 1024, 1024)];
// Create a new view with the same frame size as the superView
LoadingViewController *loadingViewController = [[LoadingViewController alloc] initWithFrame:superView.frame];
loadingViewController.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
// If something's gone wrong, abort!
if(!loadingViewController){ return nil; }
[superView addSubview:loadingViewController];
if(!loadingViewController){ return nil; }
// This is the new stuff here ;)
UIActivityIndicatorView *indicator =
[[[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleWhiteLarge] autorelease];
// Set the resizing mask so it's not stretched
UIImageView *background = [[UIImageView alloc] initWithImage:[loadingViewController addBackground]];
// Make a little bit of the superView show through
background.alpha = 0.7;
[loadingViewController addSubview:background];
indicator.autoresizingMask =
UIViewAutoresizingFlexibleTopMargin |
UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleBottomMargin |
UIViewAutoresizingFlexibleLeftMargin;
// Place it in the middle of the view
indicator.center = superView.center;
// Add it into the spinnerView
[loadingViewController addSubview:indicator];
// Start it spinning! Don't miss this step
[indicator startAnimating];
// Create a new animation
CATransition *animation = [CATransition animation];
// Set the type to a nice wee fade
[animation setType:kCATransitionFade];
// Add it to the superView
[[superView layer] addAnimation:animation forKey:#"layerAnimation"];
return loadingViewController;
}
- (UIImage *)addBackground{
cClient = [CrestronClient sharedManager];
if (cClient.isConnected == FALSE) {
[cClient connect];
}
// Create an image context (think of this as a canvas for our masterpiece) the same size as the view
UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, 1);
// Our gradient only has two locations - start and finish. More complex gradients might have more colours
size_t num_locations = 2;
// The location of the colors is at the start and end
CGFloat locations[2] = { 0.0, 1.0 };
// These are the colors! That's two RBGA values
CGFloat components[8] = {
0.4,0.4,0.4, 0.8,
0.1,0.1,0.1, 0.5 };
// Create a color space
CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB();
// Create a gradient with the values we've set up
CGGradientRef myGradient = CGGradientCreateWithColorComponents (myColorspace, components, locations, num_locations);
// Set the radius to a nice size, 80% of the width. You can adjust this
float myRadius = (self.bounds.size.width*.8)/2;
// Now we draw the gradient into the context. Think painting onto the canvas
CGContextDrawRadialGradient (UIGraphicsGetCurrentContext(), myGradient, self.center, 0, self.center, myRadius, kCGGradientDrawsAfterEndLocation);
// Rip the 'canvas' into a UIImage object
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// And release memory
CGColorSpaceRelease(myColorspace);
CGGradientRelease(myGradient);
UIGraphicsEndImageContext();
// … obvious.
return image;
}
- (void)dealloc {
[super dealloc];
}
#end
Make sure the loading view is set to its parents frame and has the proper autoresizingMask set. This would likely by UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight.
fixed the background by adding
[background setFrame:CGRectMake(0, 0, 1024, 768 )];
and fixed the centering of the circle with:
indicator.center = background.center;

How do I center a UIImageView within a full-screen UIScrollView?

In my application, I would like to present the user with a full-screen photo viewer much like the one used in the Photos app. This is just for a single photo and as such should be quite simple. I just want the user to be able to view this one photo with the ability to zoom and pan.
I have most of it working. And, if I do not center my UIImageView, everything behaves perfectly. However, I really want the UIImageView to be centered on the screen when the image is sufficiently zoomed out. I do not want it stuck to the top-left corner of the scroll view.
Once I attempt to center this view, my vertical scrollable area appears to be greater than it should be. As such, once I zoom in a little, I am able to scroll about 100 pixels past the top of the image. What am I doing wrong?
#interface MyPhotoViewController : UIViewController <UIScrollViewDelegate>
{
UIImage* photo;
UIImageView *imageView;
}
- (id)initWithPhoto:(UIImage *)aPhoto;
#end
#implementation MyPhotoViewController
- (id)initWithPhoto:(UIImage *)aPhoto
{
if (self = [super init])
{
photo = [aPhoto retain];
// Some 3.0 SDK code here to ensure this view has a full-screen
// layout.
}
return self;
}
- (void)dealloc
{
[photo release];
[imageView release];
[super dealloc];
}
- (void)loadView
{
// Set the main view of this UIViewController to be a UIScrollView.
UIScrollView *scrollView = [[UIScrollView alloc] init];
[self setView:scrollView];
[scrollView release];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Initialize the scroll view.
CGSize photoSize = [photo size];
UIScrollView *scrollView = (UIScrollView *)[self view];
[scrollView setDelegate:self];
[scrollView setBackgroundColor:[UIColor blackColor]];
// Create the image view. We push the origin to (0, -44) to ensure
// that this view displays behind the navigation bar.
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, -44.0,
photoSize.width, photoSize.height)];
[imageView setImage:photo];
[scrollView addSubview:imageView];
// Configure zooming.
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
CGFloat widthRatio = screenSize.width / photoSize.width;
CGFloat heightRatio = screenSize.height / photoSize.height;
CGFloat initialZoom = (widthRatio > heightRatio) ? heightRatio : widthRatio;
[scrollView setMaximumZoomScale:3.0];
[scrollView setMinimumZoomScale:initialZoom];
[scrollView setZoomScale:initialZoom];
[scrollView setBouncesZoom:YES];
[scrollView setContentSize:CGSizeMake(photoSize.width * initialZoom,
photoSize.height * initialZoom)];
// Center the photo. Again we push the center point up by 44 pixels
// to account for the translucent navigation bar.
CGPoint scrollCenter = [scrollView center];
[imageView setCenter:CGPointMake(scrollCenter.x,
scrollCenter.y - 44.0)];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[[self navigationController] navigationBar] setBarStyle:UIBarStyleBlackTranslucent];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent animated:YES];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[[self navigationController] navigationBar] setBarStyle:UIBarStyleDefault];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault animated:YES];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return imageView;
}
#end
This code should work on most versions of iOS (and has been tested to work on 3.1 upwards).
It's based on the Apple WWDC code for PhotoScroller.
Add the below to your subclass of UIScrollView, and replace tileContainerView with the view containing your image or tiles:
- (void)layoutSubviews {
[super layoutSubviews];
// center the image as it becomes smaller than the size of the screen
CGSize boundsSize = self.bounds.size;
CGRect frameToCenter = tileContainerView.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;
tileContainerView.frame = frameToCenter;
}
Have you checked out the UIViewAutoresizing options?
(from the documentation)
UIViewAutoresizing
Specifies how a view is automatically resized.
enum {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
typedef NSUInteger UIViewAutoresizing;
Are you using IB to add the scroll view? Change the autosizing options of the scrollview to the attached image.
I think the reason behind it is because the zoomScale applies to the whole contentSize, regardless of the actual size of the subview inside the scrollView (in your case it's an imageView). The contentSize height seems to be always equal or greater than the height of the scrollView frame, but never smaller. So when applying a zoom to it, the height of the contentSize gets multiplied by the zoomScale factor as well, that's why you're getting an extra 100-something pixels of vertical scroll.
You probably want to set the bounds of the scroll view = bounds of the image view, and then center the scroll view in its containing view. If you place a view inside a scroll view at an offset from the top, you will get that empty space above it.