NCPhotoZoomViewController.swift 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import UIKit
  2. protocol PhotoZoomViewControllerDelegate: class {
  3. func photoZoomViewController(_ photoZoomViewController: PhotoZoomViewController, scrollViewDidScroll scrollView: UIScrollView)
  4. }
  5. class PhotoZoomViewController: UIViewController {
  6. @IBOutlet weak var imageViewBottomConstraint: NSLayoutConstraint!
  7. @IBOutlet weak var imageViewLeadingConstraint: NSLayoutConstraint!
  8. @IBOutlet weak var imageViewTopConstraint: NSLayoutConstraint!
  9. @IBOutlet weak var imageViewTrailingConstraint: NSLayoutConstraint!
  10. @IBOutlet weak var scrollView: UIScrollView!
  11. @IBOutlet weak var imageView: UIImageView!
  12. weak var delegate: PhotoZoomViewControllerDelegate?
  13. var image: UIImage!
  14. var index: Int = 0
  15. var doubleTapGestureRecognizer: UITapGestureRecognizer!
  16. required init?(coder aDecoder: NSCoder) {
  17. super.init(coder: aDecoder)
  18. self.doubleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didDoubleTapWith(gestureRecognizer:)))
  19. self.doubleTapGestureRecognizer.numberOfTapsRequired = 2
  20. }
  21. override func viewDidLoad() {
  22. super.viewDidLoad()
  23. self.scrollView.delegate = self
  24. if #available(iOS 11, *) {
  25. self.scrollView.contentInsetAdjustmentBehavior = .never
  26. }
  27. self.imageView.image = self.image
  28. self.imageView.frame = CGRect(x: self.imageView.frame.origin.x,
  29. y: self.imageView.frame.origin.y,
  30. width: self.image.size.width,
  31. height: self.image.size.height)
  32. self.view.addGestureRecognizer(self.doubleTapGestureRecognizer)
  33. }
  34. override func viewDidLayoutSubviews() {
  35. super.viewDidLayoutSubviews()
  36. updateZoomScaleForSize(view.bounds.size)
  37. updateConstraintsForSize(view.bounds.size)
  38. }
  39. override func viewDidAppear(_ animated: Bool) {
  40. super.viewDidAppear(animated)
  41. updateZoomScaleForSize(view.bounds.size)
  42. updateConstraintsForSize(view.bounds.size)
  43. }
  44. override func viewSafeAreaInsetsDidChange() {
  45. //When this view's safeAreaInsets change, propagate this information
  46. //to the previous ViewController so the collectionView contentInsets
  47. //can be updated accordingly. This is necessary in order to properly
  48. //calculate the frame position for the dismiss (swipe down) animation
  49. //Get the parent view controller (ViewController) from the navigation controller
  50. guard let parentVC = self.navigationController?.viewControllers.first as? NCFiles else {
  51. return
  52. }
  53. //Update the ViewController's left and right local safeAreaInset variables
  54. //with the safeAreaInsets for this current view. These will be used to
  55. //update the contentInsets of the collectionView inside ViewController
  56. parentVC.currentLeftSafeAreaInset = self.view.safeAreaInsets.left
  57. parentVC.currentRightSafeAreaInset = self.view.safeAreaInsets.right
  58. }
  59. override func didReceiveMemoryWarning() {
  60. super.didReceiveMemoryWarning()
  61. }
  62. @objc func didDoubleTapWith(gestureRecognizer: UITapGestureRecognizer) {
  63. let pointInView = gestureRecognizer.location(in: self.imageView)
  64. var newZoomScale = self.scrollView.maximumZoomScale
  65. if self.scrollView.zoomScale >= newZoomScale || abs(self.scrollView.zoomScale - newZoomScale) <= 0.01 {
  66. newZoomScale = self.scrollView.minimumZoomScale
  67. }
  68. let width = self.scrollView.bounds.width / newZoomScale
  69. let height = self.scrollView.bounds.height / newZoomScale
  70. let originX = pointInView.x - (width / 2.0)
  71. let originY = pointInView.y - (height / 2.0)
  72. let rectToZoomTo = CGRect(x: originX, y: originY, width: width, height: height)
  73. self.scrollView.zoom(to: rectToZoomTo, animated: true)
  74. }
  75. fileprivate func updateZoomScaleForSize(_ size: CGSize) {
  76. let widthScale = size.width / imageView.bounds.width
  77. let heightScale = size.height / imageView.bounds.height
  78. let minScale = min(widthScale, heightScale)
  79. scrollView.minimumZoomScale = minScale
  80. scrollView.zoomScale = minScale
  81. scrollView.maximumZoomScale = minScale * 4
  82. }
  83. fileprivate func updateConstraintsForSize(_ size: CGSize) {
  84. let yOffset = max(0, (size.height - imageView.frame.height) / 2)
  85. imageViewTopConstraint.constant = yOffset
  86. imageViewBottomConstraint.constant = yOffset
  87. let xOffset = max(0, (size.width - imageView.frame.width) / 2)
  88. imageViewLeadingConstraint.constant = xOffset
  89. imageViewTrailingConstraint.constant = xOffset
  90. let contentHeight = yOffset * 2 + self.imageView.frame.height
  91. view.layoutIfNeeded()
  92. self.scrollView.contentSize = CGSize(width: self.scrollView.contentSize.width, height: contentHeight)
  93. }
  94. }
  95. extension PhotoZoomViewController: UIScrollViewDelegate {
  96. func viewForZooming(in scrollView: UIScrollView) -> UIView? {
  97. return imageView
  98. }
  99. func scrollViewDidZoom(_ scrollView: UIScrollView) {
  100. updateConstraintsForSize(self.view.bounds.size)
  101. }
  102. func scrollViewDidScroll(_ scrollView: UIScrollView) {
  103. self.delegate?.photoZoomViewController(self, scrollViewDidScroll: scrollView)
  104. }
  105. }