Skip to content

Instantly share code, notes, and snippets.

@albertbori
Last active April 15, 2022 08:50
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save albertbori/12cc4160e70126ddde67 to your computer and use it in GitHub Desktop.
Save albertbori/12cc4160e70126ddde67 to your computer and use it in GitHub Desktop.

##Simple Storyboard/Autolayout Full-Screen Image Viewer

Supports

  • Double-tap to zoom/unzoom
  • Panning
  • Pinch-zooming

Inspired by: http://www.raywenderlich.com/76436/use-uiscrollview-scroll-zoom-content-swift

Note: This example assumes you're using MBProgressHUD for displaying loading indicators, and SDWebImage for loading web-based images asynchronously.

###Instructions

  1. Create a new view controller via storyboard.
  2. Add a UIScollView to the view controller, and constraint it as desired.
  3. Using control-drag, set the UIScrollView's reference outlet to the @IBOutlet weak var scrollView: UIScrollView! property and the delegate to the ImageViewController class.
import UIKit
import MBProgressHUD
class ImageViewController: UIViewController, UIScrollViewDelegate {
@IBOutlet weak var scrollView: UIScrollView!
var imageURL: String?
private var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
MBProgressHUD.showHUDAddedTo(self.view, animated: true)
imageView = UIImageView()
imageView.sd_setImageWithURL(NSURL(string: imageURL!), completed: { [weak self] (image, error, cacheType, url) -> Void in
self?.configureSizeAndZoomScale(image)
MBProgressHUD.hideHUDForView(self?.view, animated: true)
})
}
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
coordinator.animateAlongsideTransition({ context in self.centerScrollViewContents() }, completion: nil)
}
@IBAction func scrollViewDoubleTapped(recognizer: UITapGestureRecognizer) {
let pointInView = recognizer.locationInView(imageView)
if scrollView.zoomScale < scrollView.maximumZoomScale {
zoomToScale(scrollView.maximumZoomScale, pointInView: pointInView)
} else {
zoomToScale(scrollView.minimumZoomScale, pointInView: pointInView)
}
}
func configureSizeAndZoomScale(image: UIImage?) {
if let image = image {
imageView.frame = CGRect(origin: CGPoint(x: 0, y: 0), size:image.size)
scrollView.addSubview(imageView)
scrollView.contentSize = image.size
let scrollViewFrame = scrollView.frame
let scaleWidth = scrollViewFrame.size.width / scrollView.contentSize.width
let scaleHeight = scrollViewFrame.size.height / scrollView.contentSize.height
let minScale = min(scaleWidth, scaleHeight)
scrollView.minimumZoomScale = minScale
scrollView.maximumZoomScale = 1.0
scrollView.zoomScale = minScale
centerScrollViewContents()
}
}
func centerScrollViewContents() {
let boundsSize = scrollView.bounds.size
var contentsFrame = imageView.frame
if contentsFrame.size.width < boundsSize.width {
contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2.0
} else {
contentsFrame.origin.x = 0.0
}
if contentsFrame.size.height < boundsSize.height {
contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2.0
} else {
contentsFrame.origin.y = 0.0
}
imageView.frame = contentsFrame
}
func zoomToScale(scale: CGFloat, pointInView: CGPoint) {
let scrollViewSize = scrollView.bounds.size
let w = scrollViewSize.width / scale
let h = scrollViewSize.height / scale
let x = pointInView.x - (w / 2.0)
let y = pointInView.y - (h / 2.0)
let rectToZoomTo = CGRectMake(x, y, w, h);
scrollView.zoomToRect(rectToZoomTo, animated: true)
}
//MARK: - UIScrollViewDelegate
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return imageView
}
func scrollViewDidZoom(scrollView: UIScrollView) {
centerScrollViewContents()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment