0

I use ImageScrollView to show image. At the begining I show only small image. And when user tries to zoom, I load big image. First I wanted to do this using this code:

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollViewCalled
{
    ImageScrollView *scroll = (ImageScrollView *)scrollViewCalled;
    UIImageView *imageView = (UIImageView *)[scroll imageView];
    return imageView;
}

- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollViewCalled withView:(UIView *)view
{
    ImageScrollView *scroll = (ImageScrollView *)scrollViewCalled;
    if (scroll != scrollViewCalled || scroll.isImageBig)
    {
        return;
    }
    scroll.userInteractionEnabled = NO;
    [self setBigImageInBackgroundForIndex:nil];
}

But it works strange: when I try to zoom, the big image is shown, but I see its maximum zoom scale, and I can't scroll to see the rest part of the image. But when I zoom one more time instead of scrolling the image, it begins to work properly and I finally can scroll the image. But I should zoom 2 times for that.

Then I tried scrollViewDidEndZooming instead scrollViewWillBeginZooming:

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollViewCalled withView:(UIView *)view atScale:(float)scale
{
    ImageScrollView *scroll = (ImageScrollView *)scrollViewCalled;
    if (scroll != scrollViewCalled || scroll.isImageBig)
    {
        return;
    }
    scroll.userInteractionEnabled = NO;
    [self setBigImageInBackgroundForIndex:nil];
}

And everything became perfect except one thing: it's too late. I zoom small image, I see it's zoomed variant, then big image loaded and I see minimum zoom for big image. For user it seems , that image came back to it's previus zoom. And only if I try to zoom one more time, I can zoom perfectly.

Thank you in advance!

here is the code for ImageScrollView:

ImageScrollView.h
#import <UIKit/UIKit.h>

@interface ImageScrollView : UIScrollView <UIScrollViewDelegate> {
    UIView        *imageView;
    NSUInteger     index;
}
@property (assign) NSUInteger index;
@property (retain, nonatomic) UIView        *imageView;
@property (assign, nonatomic) BOOL isImageBig;
@property (assign, nonatomic) BOOL hasImage;

- (void)displayImage:(UIImage *)image;
- (void)displayTiledImageNamed:(NSString *)imageName size:(CGSize)imageSize;
- (void)setMaxMinZoomScalesForCurrentBounds;

- (CGPoint)pointToCenterAfterRotation;
- (CGFloat)scaleToRestoreAfterRotation;
- (void)restoreCenterPoint:(CGPoint)oldCenter scale:(CGFloat)oldScale;

@end

ImageScrollView.m

#import "ImageScrollView.h"
#import "TilingView.h"

@implementation ImageScrollView
@synthesize index;
@synthesize imageView;
@synthesize isImageBig, hasImage;

- (id)initWithFrame:(CGRect)frame
{
    if ((self = [super initWithFrame:frame])) {
        self.showsVerticalScrollIndicator = NO;
        self.showsHorizontalScrollIndicator = NO;
        self.bouncesZoom = YES;
        self.decelerationRate = UIScrollViewDecelerationRateFast;
        self.delegate = self;        
    }
    return self;
}

- (void)dealloc
{
    [imageView release];
    [super dealloc];
}

#pragma mark -
#pragma mark Override layoutSubviews to center content

- (void)layoutSubviews 
{
    [super layoutSubviews];

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

    if ([imageView isKindOfClass:[TilingView class]]) {
        // to handle the interaction between CATiledLayer and high resolution screens, we need to manually set the
        // tiling view's contentScaleFactor to 1.0. (If we omitted this, it would be 2.0 on high resolution screens,
        // which would cause the CATiledLayer to ask us for tiles of the wrong scales.)
        imageView.contentScaleFactor = 1.0;
    }
}

#pragma mark -
#pragma mark UIScrollView delegate methods

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

#pragma mark -
#pragma mark Configure scrollView to display new image (tiled or not)

- (void)displayImage:(UIImage *)image
{
    // clear the previous imageView
    [imageView removeFromSuperview];
    [imageView release];
    imageView = nil;

    // reset our zoomScale to 1.0 before doing any further calculations
    self.zoomScale = 1.0;

    self.imageView = [[[UIImageView alloc] initWithImage:image] autorelease];
    [self addSubview:imageView];

    self.contentSize = [image size];
    [self setMaxMinZoomScalesForCurrentBounds];
    self.zoomScale = self.minimumZoomScale;
//    self.zoomScale = self.maximumZoomScale;
}


- (void)setMaxMinZoomScalesForCurrentBounds
{
    CGSize boundsSize = self.bounds.size;
    CGSize imageSize = imageView.bounds.size;

    // calculate min/max zoomscale
    CGFloat xScale = boundsSize.width / imageSize.width;    // the scale needed to perfectly fit the image width-wise
    CGFloat yScale = boundsSize.height / imageSize.height;  // the scale needed to perfectly fit the image height-wise
    CGFloat minScale = MIN(xScale, yScale);                 // use minimum of these to allow the image to become fully visible

    // on high resolution screens we have double the pixel density, so we will be seeing every pixel if we limit the
    // maximum zoom scale to 0.5.
    CGFloat maxScale = 1.0 / [[UIScreen mainScreen] scale];
//    CGFloat maxScale = 4.0 / [[UIScreen mainScreen] scale];

    // don't let minScale exceed maxScale. (If the image is smaller than the screen, we don't want to force it to be zoomed.) 
    if (minScale > maxScale) {
        minScale = maxScale;
    }

    self.maximumZoomScale = maxScale;
    self.minimumZoomScale = minScale;
}

@end
rishi
  • 11,779
  • 4
  • 40
  • 59
Paul T.
  • 4,938
  • 7
  • 45
  • 93

2 Answers2

0

Add this method:

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return imageView;
}
Paresh Navadiya
  • 38,095
  • 11
  • 81
  • 132
0

You need not do that much in fact. Create a ScrollView. Create imageview with bigger image. Set imageview's frame and scrollview's frame similar. Set the contentsize of scrollview with the images' width and height. Now, from scrollview's delegate method, do following:

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return imageView;
}
Apurv
  • 17,116
  • 8
  • 51
  • 67
  • I need to set a big image only after zooming. And imageview size should be == content size. and scroll view frame == screen frame – Paul T. Jun 26 '12 at 12:27