Complete Swift Playground Example
The simplest example I can think of is adding a UIImageView
to a UIScrollView
. This is 100% in code, you'll just need to add a PNG to the Playground. I called mine Image.png
. In a Playground you'll see the whole thing rendered in the 'Live View'. Pinch-zoom works using a Ctrl-click to place one finger on the screen and then dragging around. Until the content is zoomed in bigger than the screen panning will not work. Double-tap the image to toggle between 1x and 3x scale.
Based upon the Apple's Technical Note TN2154: UIScrollView and Autolayout
Gotcha
You'll find the whole thing very frustrating if your content is not bigger than the screen size. If your content completely fits on screen nothing will happen. That's why you must get zooming to work too. If you want to prove to yourself it works, test with a really big image (bigger than the window).
import UIKit
import PlaygroundSupport
enum TapToggle {
case Regular, Large
}
class ScrollingViewController : UIViewController
{
var tapToggle: TapToggle = .Large
var scrollView: UIScrollView?
var imageView: UIImageView?
override func viewDidLoad()
{
let image = UIImage(named: "Image")
let imageView = UIImageView(image: image)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.backgroundColor = .white
imageView.isUserInteractionEnabled = true
let scrollView = UIScrollView()
scrollView.minimumZoomScale = 0.5
scrollView.maximumZoomScale = 10.0
scrollView.delegate = self
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(imageView)
let imageViewKey = "imageView"
let imageViews = [imageViewKey: imageView]
scrollView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[\(imageViewKey)]|", options: [], metrics: nil, views: imageViews))
scrollView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[\(imageViewKey)]|", options: [], metrics: nil, views: imageViews))
self.imageView = imageView
scrollView.backgroundColor = .white
self.view.addSubview(scrollView)
let scrollViewKey = "scrollView"
let scrollViews = [scrollViewKey: scrollView]
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[\(scrollViewKey)]|", options: [], metrics: nil, views: scrollViews))
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[\(scrollViewKey)]|", options: [], metrics: nil, views: scrollViews))
self.scrollView = scrollView
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didDoubleTap(sender:)))
tapGesture.numberOfTapsRequired = 2
self.imageView?.addGestureRecognizer(tapGesture)
}
@objc
public func didDoubleTap(sender: AnyObject)
{
switch self.tapToggle {
case .Regular:
self.scrollView?.zoomScale = 1.0
self.tapToggle = .Large
case .Large:
self.scrollView?.zoomScale = 3.0
self.tapToggle = .Regular
}
}
}
extension ScrollingViewController: UIScrollViewDelegate
{
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return self.imageView
}
func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat)
{
print("\(scale)")
}
}
PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = ScrollingViewController()
scrollViewWillBeginZooming:withView:
and putting them back on inscrollViewDidEndZooming:withView:atScale:
and during the zoom it works better, but after the zoom the content is in the wrong place. – devguydavidUIScrollView
andUIPageViewController
in particular). – phu