In my iPhone app, I need to provide the user with an ability to zoom/pan a large-ish image on the screen. This is quite simple: I use UIScrollView
, set max/min scale factors and zooming/panning works as expected. Here's where things get interesting. The image is a dynamic one, received from a server. It can have any dimensions. When the image first loads, it's scaled down (if needed) to fit completely into the UIScrollView
and is centered in the scroll view - the screenshot is below:
Because the proportions of the image are different from those of the scroll view, there's white space added above and below the image so that the image is centered. However when I start zooming the image, the actual image becomes large enough to fill the whole of the scrollview viewport, therefore white paddings at top/bottom are not needed anymore, however they remain there, as can be seen from this screenshot:
I believe this is due to the fact that the UIImageView
containing the image is automatically sized to fill the whole of UIScrollView
and when zoomed, it just grows proportionally. It has scale mode set to Aspect Fit
. UIScrollView
's delegate viewForZoomingInScrollView
simply returns the image view.
I attempted to recalculate and re-set UIScrollView
, contentSize
and image view's size in scrollViewDidEndZooming
method:
CGSize imgViewSize = imageView.frame.size;
CGSize imageSize = imageView.image.size;
CGSize realImgSize;
if(imageSize.width / imageSize.height > imgViewSize.width / imgViewSize.height) {
realImgSize = CGSizeMake(imgViewSize.width, imgViewSize.width / imageSize.width * imageSize.height);
}
else {
realImgSize = CGSizeMake(imgViewSize.height / imageSize.height * imageSize.width, imgViewSize.height);
}
scrollView.contentSize = realImgSize;
CGRect fr = CGRectMake(0, 0, 0, 0);
fr.size = realImgSize;
imageView.frame = fr;
However this was only making things worse (with bounds still being there but panning not working in the vertical direction).
Is there any way to automatically reduce that whitespace as it becomes unneeded and then increment again during zoom-in? I suspect the work will need to be done in scrollViewDidEndZooming
, but I'm not too sure what that code needs to be.
Suppose we have an image view inside of scroll view. When zoom the image, you want it to be centered. It is quite simple. We just need to update the offset of the image in the method scrollViewDidZoom (remember to set delegate UIScrollViewDelegate in your code).
You can vertically center content in a scroll view by using GeometryReader to get the parent view's dimensions and setting the scroll view's content's minHeight to the parent's height. When the content is too big to fit vertically it'll just scroll like normal. Save this answer.
Analogous to different answers based on setting contentInset
, but shorter. Remember about setting scrollView.delegate
.
func scrollViewDidZoom(_ scrollView: UIScrollView) {
let offsetX = max((scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5, 0.0)
let offsetY = max((scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5, 0.0)
scrollView.contentInset = UIEdgeInsets(top: offsetY, left: offsetX, bottom: offsetY, right: offsetX);
}
If you want to take a look on a few different strategies, here is a place worth to look: github & post.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With