3

I'm having difficulties getting a tiled UIScrollView to zoom in and out correctly with pinch zooming. The issue is that when a pinch-zoom occurs, the resulting view is usually not centered in the same region.

Details: The app starts with a tiled image that is 500x500. If a user zooms in, it will snap to 1000x1000 and the tiles will redraw. For all the zoom affects, etc. I am just letting the UIScrollView do it's thing. When scrollViewDidEndZooming:withView:atScale: is called, I redraw the tiles (like you can see in many examples and other questions here).

I think that I've drilled the problem down to calculating the center of the view correctly when I get to scrollViewDidEndZooming:withView:atScale: (I can center on a known point fine after I redraw).

What I'm currently using:

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
    // as an example, create the "target" content size
    CGSize newZoomSize = CGSizeMake(1000, 1000);

    // get the center point
    CGPoint center = [scrollView contentOffset];
    center.x += [scrollView frame].width / 2;
    center.y += [scrollView frame].height / 2;

    // since pinch zoom changes the contentSize of the scroll view, translate this point to 
    // the "target" size (from the current size)
    center = [self translatePoint:center currentSize:[scrollView contentSize] newSize:newZoomSize];

    // redraw...
}

/*
    Translate the point from one size to another
*/
- (CGPoint)translatePoint:(CGPoint)origin currentSize:(CGSize)currentSize newSize:(CGSize)newSize {
    // shortcut if they are equal
    if(currentSize.width == newSize.width && currentSize.height == newSize.height){ return origin; }

    // translate
    origin.x = newSize.width * (origin.x / currentSize.width);
    origin.y = newSize.height * (origin.y / currentSize.height);
    return origin;
}

Does this seem correct? Is there a better way? Thanks!

Rob
  • 7,377
  • 7
  • 36
  • 38
  • Can you not use a gesture recognizer? Will make things so much easier on you -- but not available in 3.1 or earlier. So if you're not targeting 3.1 or earlier, I'd strongly recommend using a UIGestureRecognizer. You can get a point which is the center between the fingers. – jer Jul 13 '10 at 00:17
  • Not sure if I can drop 3.1 support, but the UIGestureRecognizer looks very nice! For now, I am going to look for a way to find this in 3.1, but the UIGestureRecognizer may be the way to go. – Rob Jul 13 '10 at 14:52

2 Answers2

1

The way I have solved this so far is to store the initial center point of the view when the zoom starts. I initially saving this value when the scrollViewDidScroll method is called (and the scroll view is zooming). When scrollViewDidEndZooming:withView:atScale: is called, I use that center point (and reset the saved value).

Rob
  • 7,377
  • 7
  • 36
  • 38
0

The center of the scrollview can be found by adding it's center property, and it's contentOffset property.

 aView.center = CGPointMake(
     self.scrollView.center.x + self.scrollView.contentOffset.x,
     self.scrollView.center.y + self.scrollView.contentOffset.y);
1dayitwillmake
  • 2,269
  • 3
  • 26
  • 35