I would like to have scroll view with an image content view. The image is actually map which is much bigger than the screen. The map should be initially in the center of the scroll view, like photos in Photos app when you turn iPhone to landscape orientation.
I did not manage to have the map in the center with correct zooming and scrolling at the same time. Provided that the map image starts from the top of the screen (in portrait orientation), the code looks something like:
- (void)loadView {
mapView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"map.jpg"]];
CGFloat mapHeight = MAP_HEIGHT * SCREEN_WIDTH / MAP_WIDTH;
mapView.frame = CGRectMake(0, 0, SCREEN_WIDTH, mapHeight);
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
scrollView.delegate = self;
scrollView.contentSize = mapView.frame.size;
scrollView.maximumZoomScale = MAP_WIDTH / SCREEN_WIDTH;
scrollView.minimumZoomScale = 1;
[scrollView addSubview:mapView];
self.view = scrollView;
}
When I move the image frame to the center, the image grows only from the top of its frame down. I tried to play around with mapView transform, with dynamically changing frame of the imageView. Nothing works for me so far.
I wish it was that simple. I did some research on the net and found that it is not just my problem, but many people are struggling with the same issue not just on iPhone, but on Apple's desktop Cocoa as well. See following links:
http://www.iphonedevsdk.com/forum/iphone-sdk-development/5740-uiimageview-uiscrollview.html
The described solution is based on the property UIViewContentModeScaleAspectFit of the image, but unfortunately it does not work very well .The image is centered and grows properly, but the bouncing area seems to be much bigger than the picture.
This guy did not get the answer either:
http://discussions.apple.com/thread.jspa?messageID=8322675
And finally, the same problem on Apple's desktop Cocoa:
http://www.cocoadev.com/index.pl?CenteringInsideNSScrollView
I suppose the solution works, but it is based on the NSClipView, which is not on iPhone...
Anybody has some solution working on iPhone?
In Monotouch that worked for me.
Note: this method sort of works. if the image is smaller than the imageView, it will scroll partially off the screen. Not a big deal, but also not as nice as the photos app.
First, it's important to understand that we are dealing with 2 views, the imageview with the image in it, and the scrollview with the imageview in it. So, first set the imageview to the size of the screen:
Then, center your image in the imageview:
Here's my entire code:
Here's an alternate solution, similar to @JosephH's answer, but this one takes into account the actual dimensions of the image. So that when the user pans/zooms, you never have more whitespace on screen than required. This is a common problem for example when showing a landscape image on a portrait screen. There's going to be whitespace above and below the image when the entire image is on screen (Aspect Fit). Then, when zooming in, the other solutions consider that whitespace as part of the image, because it's in the imageView. They will let you pan the majority of the image off screen, leaving just the whitespace visible. This looks bad for the user.
With this class, you do need to pass it the imageView it's working with. I was tempted to have it auto detect, but this is faster and you want all the speed you can get in the
layoutSubviews
method.Note: As is, this requires that AutoLayout is not enabled for the scrollView.
One elegant way to center the content of
UISCrollView
is this.Add one observer to the contentSize of your
UIScrollView
, so this method will be called everytime the content change...Now on your observer method:
You should change the
[pointer viewWithTag:100]
. Replace by your content viewUIView
.imageGallery
pointing to your window size.This will correct the center of the content everytime his size change.
NOTE: The only way this content don't works very well is with standard zoom functionality of the
UIScrollView
.Here is what I'd consider, the solution as in it behaves exactly like apple's photo app. I had been using solutions that used:
to recenter but I didn't like that solution because after the zooming was done, it'd bounce then quick 'jump' into the center which was very un-sexy. Turns out if you pretty much do the exact same logic but in this delegate function:
it both starts off centered and when you zoom out it stays centered:
Where 'imageView' is the
UIImageView
you're using.