Updating UIScrollView Content After Each Zoom

I have UIViewinside a UIScrollView. When the scale changes UIScrollView, I want to redraw everything UIViewat a new zoom level.

On iOS <3.2, I did this by resizing UIViewwithin the limits UIScrollViewto make it a new size, and then set the conversion back to Identity so that it doesn't try to resize it further. However, with iOS> = 3.2, changing the identifier also changes the UIScrollViewzoomScale property .

The result is that whenever I zoom in (say 2x), I adjust the built-in UIViewto the appropriate size and redraw it. However, now (since I reset the conversion to Identity), UIScrollViewthinking about it again in zoomScale 1, not zoomScale 2. Therefore, if I have maxXoomScale set to 2, it will still try to zoom in, which is wrong.

I was thinking about using CATiledLayer, but I don’t think that is enough for me, since I want to redraw after each scaling, and not just with certain scaling thresholds, how it is done.

Does anyone know how to perform the correct redraw UIViewwhen scaling?

+5
source share
2 answers

Tom,

Your question is a little old, but I came up with a solution for this, so I decided that I would answer in case it helps you or anyone else. The main trick is to reset the scroll in the view zoomScaleto 1, and then adjust minimumZoomScaleand maximumZoomScaleso that the user can zoom in and out as expected.

In my implementation, I have subclassed UIScrollViewand appointed him my delegate. In my subclass, I implement two delegate methods that you need to scale (shown below). contentView is a property that I added to my subclass UIScrollViewto give it a view that actually displays the content.

, init (kMinimumZoomScale kMaximumZoomScale #define ):

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        self.autoresizesSubviews = YES;
        self.showsVerticalScrollIndicator = YES;
        self.showsHorizontalScrollIndicator = NO;
        self.bouncesZoom = YES;
        self.alwaysBounceVertical = YES;
        self.delegate = self;

        self.minimumZoomScale = kMinimumZoomScale;
        self.maximumZoomScale = kMaximumZoomScale;
    }

    return self;
}

UIScrollView . ContentView zoomScale, , . drawRect .

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)aScrollView {
    return contentView;
}


- (void)scrollViewDidEndZooming:(UIScrollView *)aScrollView withView:(UIView *)view atScale:(float)scale {
    CGFloat oldZoomScale = contentView.zoomScale;
    CGSize size = self.bounds.size;

    // Figure out where the scroll view was centered so that we can
    // fix up its offset after adjusting the scaling
    CGPoint contentCenter = self.contentOffset;
    contentCenter.x += size.width / (oldZoomScale * scale) / 2;
    contentCenter.y += size.height / (oldZoomScale * scale) / 2;

    CGFloat newZoomScale = scale * oldZoomScale;
    newZoomScale = MAX(newZoomScale, kMinimumZoomscale);
    newZoomScale = MIN(newZoomScale, kMaximumZoomscale);

    // Set the scroll view zoom scale back to 1 and adjust its minimum and maximum
    // to allow the expected amount of zooming.
    self.zoomScale = 1.0;
    self.minimumZoomScale = kMinimumZoomScale / newZoomScale;
    self.maximumZoomScale = kMaximumZoomScale / newZoomScale;

    // Tell the contentView about its new scale. My contentView.zoomScale setter method
    // calls setNeedsDisplay, but you could also call it here
    contentView.zoomScale = newZoomScale;

    // My ContentView class overrides sizeThatFits to give its expected size with
    // zoomScale taken into account
    CGRect newContentSize = [contentView sizeThatFits];

    // update the content view frame and the scroll view contentSize with the new size
    contentView.frame = CGRectMake(0, 0, newContentSize.width, newContentSize.height);
    self.contentSize = newContentSize;

    // Figure out the new contentOffset so that the contentView doesn't appear to move
    CGPoint newContentOffset = CGPointMake(contentCenter.x - size.width / newZoomScale / 2,
                                           contentCenter.y - size.height / newZoomScale / 2);
    newContentOffset.x = MIN(newContentOffset.x, newContentSize.width - size.width);
    newContentOffset.x = MAX(0, newContentOffset.x);
    newContentOffset.y = MIN(newContentOffset.y, newContentSize.height - .size.height);
    newContentOffset.y = MAX(0, newContentOffset.y);
    [self setContentOffset:newContentOffset animated:NO];
}
+15

, . , :

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(double)scale{
    NSLog(@"finished zooming");

    NSLog(@"position x :%f",pin1.frame.origin.x);
    NSLog(@"position y :%f",pin1.frame.origin.y);


    CGRect frame = pin1.frame;
    frame.origin.x = pin1.frame.origin.x * scale;
    frame.origin.y = pin1.frame.origin.y * scale;
    pin1.frame = frame;

    NSLog(@"position x new :%f",pin1.frame.origin.x);
    NSLog(@"position y new:%f",pin1.frame.origin.y);

}
0

All Articles