Skip to content

Instantly share code, notes, and snippets.

@vickeryj
Created September 8, 2016 20:03
Show Gist options
  • Save vickeryj/ec24f320d8469b87258f55b697aa42f1 to your computer and use it in GitHub Desktop.
Save vickeryj/ec24f320d8469b87258f55b697aa42f1 to your computer and use it in GitHub Desktop.
Zoom into and page through an array of images
import UIKit
class FullscreenPhotoViewController: UIViewController, UIScrollViewDelegate {
// MARK: - IBOutlets
@IBOutlet weak var scrollView: UIScrollView!
// MARK: - IBActions
@IBAction func closeButtonTapped(sender: AnyObject) {
dismissViewControllerAnimated(true, completion: nil)
}
// MARK: - Private Properties
private let imageViewTag = 1
// MARK: Public Properties
var images: [UIImage]?
var currentImageIndex: Int?
// MARK: UIViewController
override func viewDidLayoutSubviews() {
setupNestedImageScrollViews()
}
override func viewDidAppear(animated: Bool) {
Analytics.service.pageView(.FullScreenPhoto)
}
// MARK: UIScrollViewDelegate
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return scrollView.viewWithTag(imageViewTag)
}
func scrollViewDidZoom(scrollView: UIScrollView) {
centerImageIfSmallerThanView(scrollView)
}
func scrollViewDidScroll(scrollView: UIScrollView) {
if scrollView == self.scrollView {
currentImageIndex = Int(round(scrollView.contentOffset.x / scrollView.bounds.width))
}
}
// MARK: Private Functions
private func setupNestedImageScrollViews() {
for view in scrollView.subviews {
view.removeFromSuperview()
}
let previousImageIndex = currentImageIndex
scrollView.bounds = view.bounds
scrollView.contentOffset = CGPointZero
if let images = images {
var imageScrollViewFrame = scrollView.bounds
for image in images {
let imageView = UIImageView(image: image)
imageView.tag = imageViewTag
let imageScrollView = UIScrollView(frame: imageScrollViewFrame)
imageScrollView.addSubview(imageView)
imageScrollView.contentSize = imageView.bounds.size
imageScrollView.delegate = self
scrollView.addSubview(imageScrollView)
zoomImageToFit(imageScrollView)
centerImageIfSmallerThanView(imageScrollView)
imageScrollViewFrame.origin.x += imageScrollViewFrame.size.width
}
scrollView.contentSize = CGSizeMake(CGFloat(images.count) * scrollView.bounds.width, scrollView.bounds.height)
currentImageIndex = previousImageIndex
setOffsetToCurrentImageIndex()
}
}
private func centerImageIfSmallerThanView(imageScrollView: UIScrollView) {
guard let imageView = imageScrollView.viewWithTag(imageViewTag) as? UIImageView,
image = imageView.image else { return }
var imageViewFrame = imageView.frame
let yOffset = max(0, (view.bounds.size.height - (image.size.height * imageScrollView.zoomScale)) / 2)
imageViewFrame.origin.y = yOffset
let xOffset = max(0, (view.bounds.size.width - (image.size.width * imageScrollView.zoomScale)) / 2)
imageViewFrame.origin.x = xOffset
imageView.frame = imageViewFrame
}
private func zoomImageToFit(imageScrollView: UIScrollView) {
guard let imageView = imageScrollView.viewWithTag(imageViewTag) as? UIImageView,
image = imageView.image else { return }
let scrollViewFrame = imageScrollView.frame
let scaleWidth = scrollViewFrame.size.width / image.size.width
let scaleHeight = scrollViewFrame.size.height / image.size.height
let minScale = min(scaleHeight, scaleWidth)
imageScrollView.minimumZoomScale = minScale
imageScrollView.maximumZoomScale = 1
imageScrollView.zoomScale = minScale
}
private func setOffsetToCurrentImageIndex() {
guard let images = images, index = currentImageIndex else { return }
if images.count > index {
scrollView.contentOffset = CGPointMake(scrollView.bounds.width * CGFloat(index), 0)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment