How to set a minimum UIPopoverController size in iOS 5? - ios5

I am using a UIPopoverController to display properties of my ContentItems. All worked fine in iOS 4.3 using presentPopoverFromRect. Some of the ContentItem rect's are fairly large, and in iOS 5, the popover re-sizes itself to fit in the margin between the rect's edges and the screen borders. In the worst cases the popover is less than 50 pixels tall and overlays the NavigationBar. Obviously not user friendly.
I've re-written the code (latest attempt below) to detect the problem cases and give the popover a 1 pixel rect at the center point of the ContentItem. This works most of the time although I'm still reverse-engineering the behavior for some boundary cases.
However I feel I must be missing something. During the iOS 5 Beta there was some discussion of the need to specify resizing masks of the Views the popover managed - but I just find it hard to believe the behavior I'm seeing is Apple fault and not mine. Advice is appreciated.
- (IBAction)handleDoubleTap:(UIGestureRecognizer *)sender
{
int subViewTag = sender.view.tag;
DLog(#":tag = %d", subViewTag);
NSString* key = [NSString stringWithFormat:#"%d", subViewTag];
ContentItemView* contentItemView = [self.contentItemViewDict objectForKey:key];
ContentItem* theContentItem = [contentItemView contentItem];
ContentItemPropertiesViewController* contentPopover = [[[ContentItemPropertiesViewController alloc] initWithNibName:#"ContentItemPropertiesViewController"
bundle:[NSBundle mainBundle]] autorelease];
contentPopover.delegate = self;
contentPopover.theItem = theContentItem;
contentPopover.theView = sender.view;
[contentPopover setContentSizeForViewInPopover:/*k_contentItemPopoverSize*/ CGSizeMake(320, 344.0f)];
UIPopoverController* popover = [[UIPopoverController alloc] initWithContentViewController:contentPopover];
popover.delegate = self;
self.contentPopoverViewController = popover;
[popover setPopoverContentSize:CGSizeMake(320, 344.0f)];
[popover release];
// Check to see if there's room for the popover around the edges of the object
CGRect popoverRect = [self rectForPopover:sender.view.frame];
if (popoverRect.origin.x == 0 && popoverRect.origin.y == 0 &&
popoverRect.size.width == 0 && popoverRect.size.height == 0) {
popoverRect = sender.view.bounds;
}
CGRect theRect = [sender.view convertRect:popoverRect
toView:self.view];
DLog(#"popoverRect %f, %f, %f, %f", theRect.origin.x, theRect.origin.y, theRect.size.width, theRect.size.height);
[self.contentPopoverViewController presentPopoverFromRect:theRect
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
- (CGRect)rectForPopover:(CGRect)viewRect
{
#define k_popoverPad 30.0f // a little extra room for the popover borders and arrow
DLog();
// Get the width and height the popover controller needs to fully display itself
CGSize popoverSize = k_contentItemPopoverSize;
CGFloat popoverWidth = popoverSize.width;
CGFloat popoverHeight = popoverSize.height;
// Get the edges of the object's rect translated to sceneView's coordinates
CGFloat leftEdge = self.sceneView.frame.origin.x + viewRect.origin.x - k_popoverPad;
CGFloat rightEdge = leftEdge + viewRect.size.width + k_popoverPad;
CGFloat topEdge = self.sceneView.frame.origin.y + viewRect.origin.y - k_popoverPad;
CGFloat bottomEdge = topEdge + viewRect.size.height + k_popoverPad;
// Get the bounds of the view
CGFloat viewRightBound = self.view.bounds.origin.x + self.view.bounds.size.width;
CGFloat viewBottomBound = self.view.bounds.origin.y + self.view.bounds.size.height;
// Compare the "margin" between the screen bounds and object's edges
// to see if the popover will fit somewhere
if (leftEdge > popoverWidth || // room on the left
topEdge > popoverHeight || // room at the top
viewRightBound - rightEdge > popoverWidth || // room to the right
viewBottomBound - bottomEdge > popoverHeight) { // room at the bottom
return CGRectZero;
} else {
// return a rect that is (essentially) the centerpoint of the object
CGRect newRect = CGRectMake((rightEdge - leftEdge) / 2.0f, (bottomEdge - topEdge) / 2.0f, 1.0f, 1.0f);
return newRect;
}
}

Related

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

iPhone : Hiding / showing Toolbar

I have a toolbar on top of my view with a back button. I would like when the view loads to appear with the toolbar hidden and then, with a touch of the button to appear animated.
--Edit--
I am not using a Navigation Controller.
Before the view is shown:
[self.navigationController setToolbarHidden:YES];
When you press the button:
[self.navigationController setToolbarHidden:NO];
Given new information - that there's no UINavigationController - things are different. Here are the relevant bits from my code...
Create the nav bar and add it to your view:
// Create the navigation bar
self.navBar = [[UINavigationBar alloc] init];
[self.view addSubview:self.navBar];
Lay it out..
- (CGRect)frameForOrientation:(UIInterfaceOrientation)theOrientation
{
UIScreen *screen = [UIScreen mainScreen];
CGRect fullScreenRect = screen.bounds; // always implicitly in Portrait orientation.
CGRect appFrame = screen.applicationFrame;
// Find status bar height by checking which dimension of the applicationFrame is narrower than screen bounds.
// Little bit ugly looking, but it'll still work even if they change the status bar height in future.
float statusBarHeight = MAX((fullScreenRect.size.width - appFrame.size.width), (fullScreenRect.size.height - appFrame.size.height));
// Initially assume portrait orientation.
float width = fullScreenRect.size.width;
float height = fullScreenRect.size.height;
// Correct for orientation.
if (UIInterfaceOrientationIsLandscape(theOrientation)) {
width = fullScreenRect.size.height;
height = fullScreenRect.size.width;
}
// Account for status bar, which always subtracts from the height (since it's always at the top of the screen).
height -= statusBarHeight;
return CGRectMake(0, statusBarHeight, width, height);
}
- (CGSize)viewSizeForOrientation:(UIInterfaceOrientation)theOrientation
{
CGRect frame = [self frameForOrientation:theOrientation];
return CGSizeMake(frame.size.width, frame.size.height);
}
- (void)layoutSubviewsForInterfaceOrientation:(UIInterfaceOrientation)theOrientation withAnimation:(BOOL)animate
{
CGSize fullSize = [self viewSizeForOrientation:theOrientation];
float width = fullSize.width;
float height = fullSize.height;
CGRect newFrame = CGRectMake(0, 0, width, height);
SubViewController *controller;
UIView *theView;
// Place the navigation bar
CGRect navBarFrame = newFrame;
navBarFrame.size.height = NAVBARHEIGHT;
self.navBar.frame = navBarFrame;
}
Create a function to who it/hide it:
- (void)showNavigationBar:(BOOL)show
{
if (show == YES && self.navBar.hidden == YES) {
// Move the frame out of sight
CGRect frame = self.navBar.frame;
frame.origin.y = -frame.size.height;
self.navBar.frame = frame;
// Display it nicely
self.navBar.hidden = NO;
frame.origin.y = 0.0;
[self.view bringSubviewToFront:self.navBar];
[UIView animateWithDuration:0.3
animations:^(void) {
self.navBar.frame = frame;
}
];
}
else if (show == NO && self.navBar.hidden == NO) {
CGRect frame = self.navBar.frame;
// Display it nicely
frame.origin.y = -frame.size.height;
[self.view bringSubviewToFront:self.navBar];
[UIView animateWithDuration:0.3
animations:^(void) {
self.navBar.frame = frame;
}
completion:^(BOOL finished) {
self.navBar.hidden = YES;
}
];
}
}
where
#define NAVBARHEIGHT 44
Here's some of tarmes's code ported to MonoTouch/c#.
public static RectangleF FrameForOrientation(UIInterfaceOrientation orientation) {
var screen = UIScreen.MainScreen;
var fullScreenRect = screen.Bounds; // always implicitly in Portrait orientation.
var appFrame = screen.ApplicationFrame;
// Find status bar height by checking which dimension of the applicationFrame is narrower than screen bounds.
// Little bit ugly looking, but it'll still work even if they change the status bar height in future.
var statusBarHeight = Math.Max((fullScreenRect.Width - appFrame.Width), (fullScreenRect.Height- appFrame.Height));
// Initially assume portrait orientation.
var width = fullScreenRect.Width;
var height = fullScreenRect.Height;
// Correct for orientation.
if (IsLandscapeOrientation(orientation)) {
width = fullScreenRect.Height;
height = fullScreenRect.Width;
}
// Account for status bar, which always subtracts from the height (since it's always at the top of the screen).
height -= statusBarHeight;
return new RectangleF(0, statusBarHeight, width, height);
}
public static SizeF SizeForOrientation(UIInterfaceOrientation orientation) {
var frame = FrameForOrientation(orientation);
return new SizeF(frame.Width, frame.Height);
}
public static bool IsLandscapeOrientation(UIInterfaceOrientation orientation) {
return
orientation == UIInterfaceOrientation.LandscapeLeft ||
orientation == UIInterfaceOrientation.LandscapeRight;
}

Infinite UIScrollView gets strange behavior in iOS4.3 not iOS5

I've implemented an infinite UIScrollView that contains UIViews. When scrolling in iOS5 (simulator and iphone) it works beautifully. But in iOS 4.3 (sim and phone) it kinda goes a bit crazy and scrolls passed more views than it should (about 10-15x more views than in iOS5). And to make it more strange it works as expected if I drag slowly so it doesn't continue scroll after I release.
The setup is kinda simple, I extend the UIScrollView class. And add UIView with a width of about 1500pt, in this I add my UIViews I want to scroll over. When scrolling the views are added and removed if they are off screen.
I think my problem lies with in this code:
- (void)recenterIfNecessary {
CGPoint currentOffset = [self contentOffset];
CGFloat contentWidth = [self contentSize].width;
CGFloat centerOffsetX = (contentWidth - [self bounds].size.width) / 2.0;
CGFloat distanceFromCenter = fabs(currentOffset.x - centerOffsetX);
UIView *image;
if (distanceFromCenter > (contentWidth / 4.0)) {
// Recenter the ScrollView so we never reach the edge
self.contentOffset = CGPointMake(centerOffsetX, currentOffset.y);
// Move visiblePhotos to new position to adjust to new contentOffset
for (image in visiblePhotos) {
CGPoint center = image.center;
center.x += (centerOffsetX - currentOffset.x);
image.center = center;
}
}
}
recenterIfNecessary is invoked here:
- (void)layoutSubviews {
[super layoutSubviews];
[self recenterIfNecessary];
[self tileImagesFromMinX:minVisibleX toMaxX:maxVisibleX];
//....
}
I've tried logging positions and offsets to try find a pattern with the difference between iOS4 & 5 with luck.
I got the concept and some code from http://developer.apple.com/videos/wwdc/2011/#advanced-scrollview-techniques (they use iOS5).
EDIT
Photos (that are put in the visiblePhotos array) are created with this methods:
- (CGFloat)placeNewImageOnRight:(CGFloat)rightEdge {
imageIndex = imageIndex < 0 ? ([reportItems count] - 1) : (imageIndex >= [reportItems count] ? 0 : imageIndex);
UIView *image = [self createItemContainer:[reportItems objectAtIndex:imageIndex]];
[visiblePhotos addObject:image];
CGRect frame = [image frame];
frame.origin.x = rightEdge;
frame.origin.y = [imageContainerView bounds].size.height - frame.size.height;
[image setFrame:frame];
imageIndex += 1;
return CGRectGetMaxX(frame);
}
- (CGFloat)placeNewImageOnLeft:(CGFloat)leftEdge {
imageIndex = imageIndex < 0 ? ([reportItems count] - 1) : (imageIndex >= [reportItems count] ? 0 : imageIndex);
UIView *image = [self createItemContainer:[reportItems objectAtIndex:imageIndex]];
[visiblePhotos insertObject:image atIndex:0];
CGRect frame = [image frame];
frame.origin.x = leftEdge - frame.size.width;
frame.origin.y = [imageContainerView bounds].size.height - frame.size.height;
[image setFrame:frame];
imageIndex -= 1;
return CGRectGetMinX(frame);
}
[self createItemContainer:[reportItems objectAtIndex:imageIndex]] creates a UIVeiw that contains a photo`.
The left and right methods are basically the same and are invoked by the method below. And tileImagesFromMinX is invoked on every frame by - (void)layoutSubviews.
- (void)tileImagesFromMinX:(CGFloat)minVisibleX toMaxX:(CGFloat)maxVisibleX {
if ([visiblePhotos count] == 0) {
[self placeNewImageOnRight:minVisibleX];
}
UIView *lastImage = [visiblePhotos lastObject];
CGFloat rightEdge = CGRectGetMaxX([lastImage frame]);
while (rightEdge < maxVisibleX) {
rightEdge = [self placeNewImageOnRight:rightEdge];
}
UIView *firstImage = [visiblePhotos objectAtIndex:0];
CGFloat leftEdge = CGRectGetMinX([firstImage frame]);
while (leftEdge > minVisibleX) {
leftEdge = [self placeNewImageOnLeft:leftEdge];
}
lastImage = [visiblePhotos lastObject];
while ([lastImage frame].origin.x > maxVisibleX) {
[lastImage removeFromSuperview];
[visiblePhotos removeLastObject];
lastImage = [visiblePhotos lastObject];
}
firstImage = [visiblePhotos objectAtIndex:0];
while (CGRectGetMaxX([firstImage frame]) < minVisibleX) {
[firstImage removeFromSuperview];
[visiblePhotos removeObjectAtIndex:0];
firstImage = [visiblePhotos objectAtIndex:0];
}
}
I've done a bunch of investigating and determined that you can't just set self.contentOffset = ...; and expect the scroll view to scroll/decelerate properly in iOS 4.3. So, even without the image tiling (and in fact you will notice this more clearly if you remove your images and just put a background on your image container view), your implementation of recenterIfNecessary will not work under 4.3 (this also affects the sample code on the developer site!).
Unfortunately, it seems the only way to work around this is to override -setContentOffset: and modify the offset there before calling super. Have a look at this question for some guidance on how to get that working correctly. I hope for your sake that this method will also work in iOS 5...

Center an UIImageView on the screen when zoom out

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;
}

How do I Change minimum Zoom scale on orientation change?

I am trying to set up an app very similar to the Photos app on the iPhone. The problem I am running into is that I cannot figure out a good way to set the minimum zoom scale and force the current zoom scale back to the minimum if it is currently smaller than the minimum.
Here is how I am currently setting up my scrollview...
- (void)viewDidLoad{
NSData * imageData = [[[NSData alloc] autorelease] initWithContentsOfURL: [NSURL URLWithString: imageURL]];
UIImage *babe = [UIImage imageWithData:imageData];
babeView = [[UIImageView alloc]
initWithImage:babe];
[self.view addSubview:babeView];
UIBabeScrollView* myScrollview = (UIBabeScrollView*)self.view;
myScrollview.frame = [UIScreen mainScreen].applicationFrame;
[myScrollview setContentSize:[babe size]];
[myScrollview setMaximumZoomScale:2.0];
// Work out a nice minimum zoom for the image - if it's smaller than the ScrollView then 1.0x zoom otherwise a scaled down zoom so it fits in the ScrollView entirely when zoomed out
CGSize imageSize = babeView.image.size;
CGSize scrollSize = myScrollview.frame.size;
CGFloat widthRatio = scrollSize.width / imageSize.width;
CGFloat heightRatio = scrollSize.height / imageSize.height;
CGFloat minimumZoom = MIN(1.0, (widthRatio > heightRatio) ? heightRatio : widthRatio);
[myScrollview setMinimumZoomScale:minimumZoom];
[myScrollview setZoomScale:minimumZoom];
My UIBabeScrollView is subclassed to overload it's layoutSubviews like so...
- (void)layoutSubviews {
[super layoutSubviews];
// center the image as it becomes smaller than the size of the screen
CGSize boundsSize = self.bounds.size;
CGRect frameToCenter = ((UIImageView*)[self.subviews objectAtIndex:0]).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;
((UIImageView*)[self.subviews objectAtIndex:0]).frame = frameToCenter;
}
The affect I am going for is that the image is always centered, and cannot be zoomed out more than the width or height of the image.
Right now this works fine in portrait mode, but when it is switched to landscape, the zoom scales are incorrect.
Any help would be appreciated, as I am still a fledgling iphone app developer.
In your view controller, implement -willRotateToInterfaceOrientation:duration:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
if (toInterfaceOrientation == UIDeviceOrientationLandscapeLeft ||
toInterfaceOrientation == UIDeviceOrientationLandscapeRight) {
[myScrollview setMinimumZoomScale:yourLandscapeMinimumZoomValue];
[myScrollview setZoomScale:yourLandscapeMinimumZoomValue];
} else {
[myScrollview setMinimumZoomScale:yourPortraitMinimumZoomValue];
[myScrollview setZoomScale:yourPortraitMinimumZoomValue];
}
}
Also another point, just for information. I was trying the [scrollview setZoomScale: :animated] method. On orientation change, it would not Scale to the required value.
It results in an uncompleted animation.