NCPhotoPageContainerViewController.swift 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. import UIKit
  2. protocol PhotoPageContainerViewControllerDelegate: class {
  3. func containerViewController(_ containerViewController: PhotoPageContainerViewController, indexDidUpdate currentIndex: Int)
  4. }
  5. class PhotoPageContainerViewController: UIViewController, UIGestureRecognizerDelegate {
  6. enum ScreenMode {
  7. case full, normal
  8. }
  9. var currentMode: ScreenMode = .normal
  10. weak var delegate: PhotoPageContainerViewControllerDelegate?
  11. var pageViewController: UIPageViewController {
  12. return self.children[0] as! UIPageViewController
  13. }
  14. var currentViewController: PhotoZoomViewController {
  15. return self.pageViewController.viewControllers![0] as! PhotoZoomViewController
  16. }
  17. var photos: [UIImage]!
  18. var currentIndex = 0
  19. var nextIndex: Int?
  20. var panGestureRecognizer: UIPanGestureRecognizer!
  21. var singleTapGestureRecognizer: UITapGestureRecognizer!
  22. var transitionController = ZoomTransitionController()
  23. override func viewDidLoad() {
  24. super.viewDidLoad()
  25. self.pageViewController.delegate = self
  26. self.pageViewController.dataSource = self
  27. self.panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(didPanWith(gestureRecognizer:)))
  28. self.panGestureRecognizer.delegate = self
  29. self.pageViewController.view.addGestureRecognizer(self.panGestureRecognizer)
  30. self.singleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didSingleTapWith(gestureRecognizer:)))
  31. self.pageViewController.view.addGestureRecognizer(self.singleTapGestureRecognizer)
  32. let vc = UIStoryboard(name: "NCViewerImage", bundle: nil).instantiateViewController(withIdentifier: "\(PhotoZoomViewController.self)") as! PhotoZoomViewController
  33. vc.delegate = self
  34. vc.index = self.currentIndex
  35. vc.image = self.photos[self.currentIndex]
  36. self.singleTapGestureRecognizer.require(toFail: vc.doubleTapGestureRecognizer)
  37. let viewControllers = [
  38. vc
  39. ]
  40. self.pageViewController.setViewControllers(viewControllers, direction: .forward, animated: true, completion: nil)
  41. }
  42. func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
  43. if let gestureRecognizer = gestureRecognizer as? UIPanGestureRecognizer {
  44. let velocity = gestureRecognizer.velocity(in: self.view)
  45. var velocityCheck : Bool = false
  46. if UIDevice.current.orientation.isLandscape {
  47. velocityCheck = velocity.x < 0
  48. }
  49. else {
  50. velocityCheck = velocity.y < 0
  51. }
  52. if velocityCheck {
  53. return false
  54. }
  55. }
  56. return true
  57. }
  58. func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
  59. if otherGestureRecognizer == self.currentViewController.scrollView.panGestureRecognizer {
  60. if self.currentViewController.scrollView.contentOffset.y == 0 {
  61. return true
  62. }
  63. }
  64. return false
  65. }
  66. override func didReceiveMemoryWarning() {
  67. super.didReceiveMemoryWarning()
  68. // Dispose of any resources that can be recreated.
  69. }
  70. @objc func didPanWith(gestureRecognizer: UIPanGestureRecognizer) {
  71. switch gestureRecognizer.state {
  72. case .began:
  73. self.currentViewController.scrollView.isScrollEnabled = false
  74. self.transitionController.isInteractive = true
  75. let _ = self.navigationController?.popViewController(animated: true)
  76. case .ended:
  77. if self.transitionController.isInteractive {
  78. self.currentViewController.scrollView.isScrollEnabled = true
  79. self.transitionController.isInteractive = false
  80. self.transitionController.didPanWith(gestureRecognizer: gestureRecognizer)
  81. }
  82. default:
  83. if self.transitionController.isInteractive {
  84. self.transitionController.didPanWith(gestureRecognizer: gestureRecognizer)
  85. }
  86. }
  87. }
  88. @objc func didSingleTapWith(gestureRecognizer: UITapGestureRecognizer) {
  89. if self.currentMode == .full {
  90. changeScreenMode(to: .normal)
  91. self.currentMode = .normal
  92. } else {
  93. changeScreenMode(to: .full)
  94. self.currentMode = .full
  95. }
  96. }
  97. func changeScreenMode(to: ScreenMode) {
  98. if to == .full {
  99. self.navigationController?.setNavigationBarHidden(true, animated: false)
  100. UIView.animate(withDuration: 0.25,
  101. animations: {
  102. self.view.backgroundColor = .black
  103. }, completion: { completed in
  104. })
  105. } else {
  106. self.navigationController?.setNavigationBarHidden(false, animated: false)
  107. UIView.animate(withDuration: 0.25,
  108. animations: {
  109. if #available(iOS 13.0, *) {
  110. self.view.backgroundColor = .systemBackground
  111. } else {
  112. self.view.backgroundColor = .white
  113. }
  114. }, completion: { completed in
  115. })
  116. }
  117. }
  118. }
  119. extension PhotoPageContainerViewController: UIPageViewControllerDelegate, UIPageViewControllerDataSource {
  120. func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
  121. if currentIndex == 0 {
  122. return nil
  123. }
  124. let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "\(PhotoZoomViewController.self)") as! PhotoZoomViewController
  125. vc.delegate = self
  126. vc.image = self.photos[currentIndex - 1]
  127. vc.index = currentIndex - 1
  128. self.singleTapGestureRecognizer.require(toFail: vc.doubleTapGestureRecognizer)
  129. return vc
  130. }
  131. func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
  132. if currentIndex == (self.photos.count - 1) {
  133. return nil
  134. }
  135. let vc = UIStoryboard(name: "NCViewerImage", bundle: nil).instantiateViewController(withIdentifier: "\(PhotoZoomViewController.self)") as! PhotoZoomViewController
  136. vc.delegate = self
  137. self.singleTapGestureRecognizer.require(toFail: vc.doubleTapGestureRecognizer)
  138. vc.image = self.photos[currentIndex + 1]
  139. vc.index = currentIndex + 1
  140. return vc
  141. }
  142. func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
  143. guard let nextVC = pendingViewControllers.first as? PhotoZoomViewController else {
  144. return
  145. }
  146. self.nextIndex = nextVC.index
  147. }
  148. func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
  149. if (completed && self.nextIndex != nil) {
  150. previousViewControllers.forEach { vc in
  151. let zoomVC = vc as! PhotoZoomViewController
  152. zoomVC.scrollView.zoomScale = zoomVC.scrollView.minimumZoomScale
  153. }
  154. self.currentIndex = self.nextIndex!
  155. self.delegate?.containerViewController(self, indexDidUpdate: self.currentIndex)
  156. }
  157. self.nextIndex = nil
  158. }
  159. }
  160. extension PhotoPageContainerViewController: PhotoZoomViewControllerDelegate {
  161. func photoZoomViewController(_ photoZoomViewController: PhotoZoomViewController, scrollViewDidScroll scrollView: UIScrollView) {
  162. if scrollView.zoomScale != scrollView.minimumZoomScale && self.currentMode != .full {
  163. self.changeScreenMode(to: .full)
  164. self.currentMode = .full
  165. }
  166. }
  167. }
  168. extension PhotoPageContainerViewController: ZoomAnimatorDelegate {
  169. func transitionWillStartWith(zoomAnimator: ZoomAnimator) {
  170. }
  171. func transitionDidEndWith(zoomAnimator: ZoomAnimator) {
  172. }
  173. func referenceImageView(for zoomAnimator: ZoomAnimator) -> UIImageView? {
  174. return self.currentViewController.imageView
  175. }
  176. func referenceImageViewFrameInTransitioningView(for zoomAnimator: ZoomAnimator) -> CGRect? {
  177. return self.currentViewController.scrollView.convert(self.currentViewController.imageView.frame, to: self.currentViewController.view)
  178. }
  179. }