Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keep zoomable image in center of UIScrollView

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:

enter image description here

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:

enter image description here

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.

like image 807
Aleks G Avatar asked Dec 28 '12 12:12

Aleks G


People also ask

How do I center an image in scrollView?

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).

How do I center a view in scrollView Swiftui?

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.


1 Answers

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.

like image 54
Mikolaj Avatar answered Sep 17 '22 20:09

Mikolaj