Fitting an Image to Screen on Rotation iPhone / iPad ?

Posted by user356937 on Stack Overflow See other posts from Stack Overflow or by user356937
Published on 2010-06-02T22:29:45Z Indexed on 2010/06/02 22:34 UTC
Read the original article Hit count: 633

Filed under:

I have been playing around with one of the iPhone examples from Apple' web site (ScrollViewSuite) . I am trying to tweak it a bit so that when I rotate the the iPad the image will fit into the screen in landscape mode vertical. I have been successful in getting the image to rotate, but the image is larger than the height of the landscape screen, so the bottom is below the screen. I would like to image to scale to the height of the landscape screen.

I have been playing around with various autoSizingMask attributes without success.

The imageView is called "zoomView" this is the actual image which loads into a scrollView called imageScrollView.

I am trying to achieve the screen to rotate and look like this....

olsonvox.com/photos/correct.png

However, this is what My screen is looking like.

olsonvox.com/photos/incorrect.png

I would really appreciate some advice or guidance. Below is the RootViewController.m for the project.

  • Blade

    #

    import "RootViewController.h"
    
    
    
    #define ZOOM_VIEW_TAG 100
    #define ZOOM_STEP 1.5
    
    
    #define THUMB_HEIGHT 150
    #define THUMB_V_PADDING 25
    #define THUMB_H_PADDING 25
    #define CREDIT_LABEL_HEIGHT 25
    
    
    #define AUTOSCROLL_THRESHOLD 30
    
    
    @interface RootViewController (ViewHandlingMethods)
    - (void)toggleThumbView;
    - (void)pickImageNamed:(NSString *)name;
    - (NSArray *)imageNames;
    - (void)createThumbScrollViewIfNecessary;
    - (void)createSlideUpViewIfNecessary;
    @end
    
    
    @interface RootViewController (AutoscrollingMethods)
    - (void)maybeAutoscrollForThumb:(ThumbImageView *)thumb;
    - (void)autoscrollTimerFired:(NSTimer *)timer;
    - (void)legalizeAutoscrollDistance;
    - (float)autoscrollDistanceForProximityToEdge:(float)proximity;
    @end
    
    
    @interface RootViewController (UtilityMethods)
    - (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center;
    @end
    
    
    @implementation RootViewController
    
    
    - (void)loadView {
        [super loadView];
    
    
        imageScrollView = [[UIScrollView alloc] initWithFrame:[[self view]bounds]];
    
    
     // this code makes the image resize to the width and height properly. 
     imageScrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin|  UIViewAutoresizingFlexibleBottomMargin| UIViewAutoresizingFlexibleBottomMargin;
    
    
     // TRY SETTNG CENTER HERE SOMEHOW>....
    
    
     [imageScrollView setBackgroundColor:[UIColor blackColor]];
        [imageScrollView setDelegate:self];
        [imageScrollView setBouncesZoom:YES];
        [[self view] addSubview:imageScrollView];
     [self toggleThumbView];
    
    
     // intitializes with the first image.
    
    
        [self pickImageNamed:@"lookbook1"];
    }
    
    
    - (void)dealloc {
        [imageScrollView release];
        [slideUpView release];
        [thumbScrollView release];
        [super dealloc];
    }
    
    
    #pragma mark UIScrollViewDelegate methods
    
    
    - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
        UIView *view = nil;
        if (scrollView == imageScrollView) {
            view = [imageScrollView viewWithTag:ZOOM_VIEW_TAG];
        }
        return view;
    }
    
    
    /************************************** NOTE **************************************/
    /* The following delegate method works around a known bug in zoomToRect:animated: */
    /* In the next release after 3.0 this workaround will no longer be necessary      */
    /**********************************************************************************/
    - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
        [scrollView setZoomScale:scale+0.01 animated:NO];
        [scrollView setZoomScale:scale animated:NO];
    }
    
    
    #pragma mark TapDetectingImageViewDelegate methods
    
    
    - (void)tapDetectingImageView:(TapDetectingImageView *)view gotSingleTapAtPoint:(CGPoint)tapPoint {
        // Single tap shows or hides drawer of thumbnails.
        [self toggleThumbView];
    }
    
    
    - (void)tapDetectingImageView:(TapDetectingImageView *)view gotDoubleTapAtPoint:(CGPoint)tapPoint {
        // double tap zooms in
        float newScale = [imageScrollView zoomScale] * ZOOM_STEP;
        CGRect zoomRect = [self zoomRectForScale:newScale withCenter:tapPoint];
        [imageScrollView zoomToRect:zoomRect animated:YES];
    }
    
    
    - (void)tapDetectingImageView:(TapDetectingImageView *)view gotTwoFingerTapAtPoint:(CGPoint)tapPoint {
        // two-finger tap zooms out
        float newScale = [imageScrollView zoomScale] / ZOOM_STEP;
        CGRect zoomRect = [self zoomRectForScale:newScale withCenter:tapPoint];
        [imageScrollView zoomToRect:zoomRect animated:YES];
    }
    
    
    #pragma mark ThumbImageViewDelegate methods
    
    
    - (void)thumbImageViewWasTapped:(ThumbImageView *)tiv {
        [self pickImageNamed:[tiv imageName]];
        [self toggleThumbView];
    }
    
    
    - (void)thumbImageViewStartedTracking:(ThumbImageView *)tiv {
        [thumbScrollView bringSubviewToFront:tiv];
    }
    
    
    // CONTROLS DRAGGING AND DROPPING THUMBNAILS...
    
    
    - (void)thumbImageViewMoved:(ThumbImageView *)draggingThumb {
    
    
        // check if we've moved close enough to an edge to autoscroll, or far enough away to stop autoscrolling
        [self maybeAutoscrollForThumb:draggingThumb];
    
    
        /* The rest of this method handles the reordering of thumbnails in the thumbScrollView. See  */
        /* ThumbImageView.h and ThumbImageView.m for more information about how this works.          */
    
    
        // we'll reorder only if the thumb is overlapping the scroll view
        if (CGRectIntersectsRect([draggingThumb frame], [thumbScrollView bounds])) {        
    
    
            BOOL draggingRight = [draggingThumb frame].origin.x > [draggingThumb home].origin.x ? YES : NO;
    
    
            /* we're going to shift over all the thumbs who live between the home of the moving thumb */
            /* and the current touch location. A thumb counts as living in this area if the midpoint  */
            /* of its home is contained in the area.                                                  */
            NSMutableArray *thumbsToShift = [[NSMutableArray alloc] init];
    
    
            // get the touch location in the coordinate system of the scroll view
            CGPoint touchLocation = [draggingThumb convertPoint:[draggingThumb touchLocation] toView:thumbScrollView];
    
    
            // calculate minimum and maximum boundaries of the affected area
            float minX = draggingRight ? CGRectGetMaxX([draggingThumb home]) : touchLocation.x;
            float maxX = draggingRight ? touchLocation.x : CGRectGetMinX([draggingThumb home]);
    
    
            // iterate through thumbnails and see which ones need to move over
            for (ThumbImageView *thumb in [thumbScrollView subviews]) {
    
    
                // skip the thumb being dragged
                if (thumb == draggingThumb) continue;
    
    
                // skip non-thumb subviews of the scroll view (such as the scroll indicators)
                if (! [thumb isMemberOfClass:[ThumbImageView class]]) continue;
    
    
                float thumbMidpoint = CGRectGetMidX([thumb home]);
                if (thumbMidpoint >= minX && thumbMidpoint <= maxX) {
                    [thumbsToShift addObject:thumb];
                }
            }
    
    
            // shift over the other thumbs to make room for the dragging thumb. (if we're dragging right, they shift to the left)
            float otherThumbShift = ([draggingThumb home].size.width + THUMB_H_PADDING) * (draggingRight ? -1 : 1);
    
    
            // as we shift over the other thumbs, we'll calculate how much the dragging thumb's home is going to move
            float draggingThumbShift = 0.0;
    
    
            // send each of the shifting thumbs to its new home
            for (ThumbImageView *otherThumb in thumbsToShift) {
                CGRect home = [otherThumb home];
                home.origin.x += otherThumbShift;
                [otherThumb setHome:home];
                [otherThumb goHome];
                draggingThumbShift += ([otherThumb frame].size.width + THUMB_H_PADDING) * (draggingRight ? 1 : -1);
            }
    
    
            // change the home of the dragging thumb, but don't send it there because it's still being dragged
            CGRect home = [draggingThumb home];
            home.origin.x += draggingThumbShift;
            [draggingThumb setHome:home];
        }
    }
    
    
    - (void)thumbImageViewStoppedTracking:(ThumbImageView *)tiv {
        // if the user lets go of the thumb image view, stop autoscrolling
        [autoscrollTimer invalidate];
        autoscrollTimer = nil;
    }
    
    
    #pragma mark Autoscrolling methods
    
    
    - (void)maybeAutoscrollForThumb:(ThumbImageView *)thumb {
    
    
        autoscrollDistance = 0;
    
    
        // only autoscroll if the thumb is overlapping the thumbScrollView
        if (CGRectIntersectsRect([thumb frame], [thumbScrollView bounds])) {
    
    
            CGPoint touchLocation = [thumb convertPoint:[thumb touchLocation] toView:thumbScrollView];
            float distanceFromLeftEdge  = touchLocation.x - CGRectGetMinX([thumbScrollView bounds]);
            float distanceFromRightEdge = CGRectGetMaxX([thumbScrollView bounds]) - touchLocation.x;
    
    
            if (distanceFromLeftEdge < AUTOSCROLL_THRESHOLD) {
                autoscrollDistance = [self autoscrollDistanceForProximityToEdge:distanceFromLeftEdge] * -1; // if scrolling left, distance is negative
            } else if (distanceFromRightEdge < AUTOSCROLL_THRESHOLD) {
                autoscrollDistance = [self autoscrollDistanceForProximityToEdge:distanceFromRightEdge];
            }        
        }
    
    
        // if no autoscrolling, stop and clear timer
        if (autoscrollDistance == 0) {
            [autoscrollTimer invalidate];
            autoscrollTimer = nil;
        } 
    
    
        // otherwise create and start timer (if we don't already have a timer going)
        else if (autoscrollTimer == nil) {
            autoscrollTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / 60.0)
                                                               target:self 
                                                             selector:@selector(autoscrollTimerFired:) 
                                                             userInfo:thumb 
                                                              repeats:YES];
        } 
    }
    
    
    - (float)autoscrollDistanceForProximityToEdge:(float)proximity {
        // the scroll distance grows as the proximity to the edge decreases, so that moving the thumb
        // further over results in faster scrolling.
        return ceilf((AUTOSCROLL_THRESHOLD - proximity) / 5.0);
    }
    
    
    - (void)legalizeAutoscrollDistance {
        // makes sure the autoscroll distance won't result in scrolling past the content of the scroll view
        float minimumLegalDistance = [thumbScrollView contentOffset].x * -1;
        float maximumLegalDistance = [thumbScrollView contentSize].width - ([thumbScrollView frame].size.width + [thumbScrollView contentOffset].x);
        autoscrollDistance = MAX(autoscrollDistance, minimumLegalDistance);
        autoscrollDistance = MIN(autoscrollDistance, maximumLegalDistance);
    }
    
    
    - (void)autoscrollTimerFired:(NSTimer*)timer {
        [self legalizeAutoscrollDistance];
    
    
        // autoscroll by changing content offset
        CGPoint contentOffset = [thumbScrollView contentOffset];
        contentOffset.x += autoscrollDistance;
        [thumbScrollView setContentOffset:contentOffset];
    
    
        // adjust thumb position so it appears to stay still
        ThumbImageView *thumb = (ThumbImageView *)[timer userInfo];
        [thumb moveByOffset:CGPointMake(autoscrollDistance, 0)];
    }
    
    
    #pragma mark View handling methods
    
    
    - (void)toggleThumbView {
        [self createSlideUpViewIfNecessary]; // no-op if slideUpView has already been created
        CGRect frame = [slideUpView frame];
        if (thumbViewShowing) {
            frame.origin.y = 0;
        } else {
            frame.origin.y = -225;
        }
    
    
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:0.3];
        [slideUpView setFrame:frame];
        [UIView commitAnimations];
    
    
        thumbViewShowing = !thumbViewShowing;
    }
    
    
    - (void)pickImageNamed:(NSString *)name {
    
    
        // first remove previous image view, if any
        [[imageScrollView viewWithTag:ZOOM_VIEW_TAG] removeFromSuperview];
    
    
        UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"%@.jpg", name]];
        TapDetectingImageView *zoomView = [[TapDetectingImageView alloc] initWithImage:image];
    
    
     zoomView.autoresizingMask = UIViewAutoresizingFlexibleWidth ;
    
    
        [zoomView setDelegate:self];
        [zoomView setTag:ZOOM_VIEW_TAG];
        [imageScrollView addSubview:zoomView];
        [imageScrollView setContentSize:[zoomView frame].size];
        [zoomView release];
    
    
        // choose minimum scale so image width fits screen
        float minScale  = [imageScrollView frame].size.width  / [zoomView frame].size.width;
        [imageScrollView setMinimumZoomScale:minScale];
        [imageScrollView setZoomScale:minScale];
        [imageScrollView setContentOffset:CGPointZero];
    }
    
    
    - (NSArray *)imageNames {
    
    
        // the filenames are stored in a plist in the app bundle, so create array by reading this plist
        NSString *path = [[NSBundle mainBundle] pathForResource:@"Images" ofType:@"plist"];
        NSData *plistData = [NSData dataWithContentsOfFile:path];
        NSString *error; NSPropertyListFormat format;
        NSArray *imageNames = [NSPropertyListSerialization propertyListFromData:plistData
                                                               mutabilityOption:NSPropertyListImmutable
                                                                         format:&format
                                                               errorDescription:&error];
        if (!imageNames) {
            NSLog(@"Failed to read image names. Error: %@", error);
            [error release];
        }
    
    
        return imageNames;
    }
    
    
    - (void)createSlideUpViewIfNecessary {
    
    
        if (!slideUpView) {
    
    
            [self createThumbScrollViewIfNecessary];
    
    
            CGRect bounds = [[self view] bounds];
            float thumbHeight = [thumbScrollView frame].size.height;
            float labelHeight = CREDIT_LABEL_HEIGHT;
    
    
            // create label giving credit for images
            UILabel *creditLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, thumbHeight, bounds.size.width, labelHeight)];
    
    
            [creditLabel setBackgroundColor:[UIColor clearColor]];
            [creditLabel setTextColor:[UIColor whiteColor]];
    
    
     // [creditLabel setFont:[UIFont fontWithName:@"Helvetica" size:16]];
     // [creditLabel setText:@"SAMPLE TEXT"];
    
    
            [creditLabel setTextAlignment:UITextAlignmentCenter];        
    
    
            // create container view that will hold scroll view and label
            CGRect frame = CGRectMake(0.0, -225.00, bounds.size.width+256, thumbHeight + labelHeight);
      slideUpView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
            slideUpView = [[UIView alloc] initWithFrame:frame];
            [slideUpView setBackgroundColor:[UIColor blackColor]];
            [slideUpView setOpaque:NO];
            [slideUpView setAlpha:.75];
            [[self view] addSubview:slideUpView];
    
    
            // add subviews to container view
            [slideUpView addSubview:thumbScrollView];
            [slideUpView addSubview:creditLabel];
            [creditLabel release];   
    
    
        }    
    }
    
    
    - (void)createThumbScrollViewIfNecessary {
    
    
        if (!thumbScrollView) {        
    
    
            float scrollViewHeight = THUMB_HEIGHT + THUMB_V_PADDING;
            float scrollViewWidth  = [[self view] bounds].size.width;
            thumbScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, scrollViewWidth, scrollViewHeight)];
            [thumbScrollView setCanCancelContentTouches:NO];
            [thumbScrollView setClipsToBounds:NO];
    
    
            // now place all the thumb views as subviews of the scroll view 
            // and in the course of doing so calculate the content width
            float xPosition = THUMB_H_PADDING;
            for (NSString *name in [self imageNames]) {
                UIImage *thumbImage = [UIImage imageNamed:[NSString stringWithFormat:@"%@_thumb.jpg", name]];
                if (thumbImage) {
                    ThumbImageView *thumbView = [[ThumbImageView alloc] initWithImage:thumbImage];
                    [thumbView setDelegate:self];
                    [thumbView setImageName:name];
                    CGRect frame = [thumbView frame];
                    frame.origin.y = THUMB_V_PADDING;
                    frame.origin.x = xPosition;
                    [thumbView setFrame:frame];
                    [thumbView setHome:frame];
                    [thumbScrollView addSubview:thumbView];
                    [thumbView release];
                    xPosition += (frame.size.width + THUMB_H_PADDING);
                }
            }
            [thumbScrollView setContentSize:CGSizeMake(xPosition, scrollViewHeight)];
        }    
    }
    
    
    #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;
    }
    
    
    #pragma mark -
    #pragma mark Rotation support
    
    
    // Ensure that the view controller supports rotation and that the split view can therefore show in both portrait and landscape.
    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
     return YES;
    }
    
    
    @end
    

© Stack Overflow or respective owner

Related posts about iphone-sdk