There’s nothing like the perfect image to make your app shine. But what if you want your app users to actually engage and interact with an image? Maybe they want to zoom in, pan around, really get to grips with the pixels?
In this tutorial, we’re going to build a zoomable, pan-able image view to do exactly that.
They say a picture is worth a thousand words - but it doesn’t have to take a thousand lines of code! For our zoomable image view, we’re going to be making use of the zoom and pan functionality of UIScrollView. Essentially, we will nest a UIImageView containing our image within a UIScrollView that will handle all the zoom, pan (and tap!) gestures that we throw at it.
Let’s start by creating a PanZoomImageView class that subclasses UIScrollView. We'll initialize the class with a UIImageView that will be added as a subview. We want to be able to use PanZoomImageView both programmatically and via Interface Builder, so let’s handle the different initializers and create a common init:
In commonInit(), we're centering the image view and setting it's height and width, rather than pinning it to the parent view. That way, the scroll view will get its content size from the image view.
We need to actually set up our scroll view to make it zoomable and pan-able. This involves setting a min and max zoom level, and specifying the UIView to be used when the user zooms in (in our case, it'll be the image view). Let's setup the scroll view (adding some comments for clarity):
Here, we set the min and max zoom levels, ensure that the scroll indicators are hidden (we don't want them spoiling our beautiful image!), and then we set the PanZoomImageView class as the scroll view delegate. Xcode will probably start complaining because PanZoomImageView doesn't conform to UIScrollViewDelegate yet - let's do that next:
This is pretty simple - we want our image to be the view that gets displayed when zooming and panning, so we just return our imageView.
Great! We've got a UIImageView nested within a UIScrollView, and everything should be scrollable and pan-able. How do we actually set our image though? We'll do that by adding an imageName string to our class, and updating the UIImageView when the string changes. We'll also mark imageName as @IBInspectable so that it can be set via Interface Builder:
Ok, I think we're ready to use our new class! Open up Main.storyboard and add a view, pinning it to the parent view however you like. Next, select the view, navigate to the Identity Inspector, and set the class to PanZoomImageView.
Navigate to the Attributes Inspector, and you should see the 'Image Name' attribute (this represents the imageName string that we set as @IBInspectable!). Type the name of the image you'd like to nest in the view here.
It's time to build and run! All being well, you should see something like the following. Try panning and zooming (hold the 'option' key if you're using the simulator) - you’ll get a whole new perspective on your image!
That's great when using interface builder - but what if you want to initialize the view programmatically? Let's add another initializer to our class so that we can set the image name in code:
(Notice that we don't need to call commonInit() here - this gets called in a different initializer when we call init(frame: .zero))
And that's it! We can now initialize our view programmatically by passing an image name like this:
Let's take a look at our class in its entirety:
A common functionality for zoomable views is the ability to double-tap to zoom in and out. This is a relatively simple addition to our class, so let's add that next. We'll create a UITapGestureRecognizer and use it to change the scroll view's zoom scale when a user double-taps:
That's it! We can now double tap to zoom in / zoom out on our image.
This is a great reusable class that you can pull out whenever you want to make an image zoomable! Adding this extra functionality can really help people engage with the images you display in your app, and is often functionality that user's have come to expect and require.
This doesn't just apply to image views either - if you wanted to make a UIView zoomable, you could take the same approach, initializing your class with a UIView instead of an image name. Something to try out!
Search over 300 blog posts from our team
Subscribe to our monthly digest of blogs to stay in the loop and come with us on our journey to make things better!