InteractiveAnimator.swift 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. //
  2. // Created by Jake Lin on 4/5/16.
  3. // Copyright © 2016 IBAnimatable. All rights reserved.
  4. //
  5. import UIKit
  6. // Super abstract class for all interactive animator subclasses
  7. public class InteractiveAnimator: UIPercentDrivenInteractiveTransition {
  8. internal(set) public var interacting = false
  9. // transitionType: Used to deteminate pop or dismiss
  10. let transitionType: TransitionType
  11. // interactiveGestureType: Used to deteminate gesture type (direction)
  12. let interactiveGestureType: InteractiveGestureType
  13. // viewController: the viewController will connect to the gestureRecognizer
  14. weak var viewController: UIViewController?
  15. // gestureRecognizer: the gesture recognizer to handle gesture
  16. var gestureRecognizer: UIGestureRecognizer?
  17. init(interactiveGestureType: InteractiveGestureType, transitionType: TransitionType) {
  18. self.interactiveGestureType = interactiveGestureType
  19. self.transitionType = transitionType
  20. super.init()
  21. }
  22. deinit {
  23. if let gestureRecognizer = gestureRecognizer, let view = viewController?.view {
  24. gestureRecognizer.removeTarget(self, action: #selector(handleGesture(for:)))
  25. view.removeGestureRecognizer(gestureRecognizer)
  26. }
  27. }
  28. func connectGestureRecognizer(to viewController: UIViewController) {
  29. self.viewController = viewController
  30. let gestureRecognizerType = makeGestureRecognizer()
  31. gestureRecognizer = gestureRecognizerType
  32. if let gestureRecognizer = gestureRecognizer {
  33. self.viewController?.view.addGestureRecognizer(gestureRecognizer)
  34. }
  35. }
  36. @objc
  37. func handleGesture(for gestureRecognizer: UIGestureRecognizer) {
  38. let (progress, shouldFinishInteractiveTransition) = calculateProgress(for: gestureRecognizer)
  39. switch gestureRecognizer.state {
  40. case .began:
  41. guard shouldBeginProgress(for: gestureRecognizer) else {
  42. return
  43. }
  44. interacting = true
  45. switch transitionType {
  46. case .navigationTransition(.pop):
  47. if let navigationController = viewController?.navigationController {
  48. navigationController.popViewController(animated: true)
  49. }
  50. case .presentationTransition(.dismissal):
  51. viewController?.dismiss(animated: true, completion: nil)
  52. default:
  53. break
  54. }
  55. case .changed:
  56. update(progress)
  57. case .cancelled, .ended:
  58. interacting = false
  59. if shouldFinishInteractiveTransition {
  60. finish()
  61. } else {
  62. cancel()
  63. }
  64. default:
  65. // Something happened then cancel the transition.
  66. interacting = false
  67. cancel()
  68. }
  69. }
  70. // Because Swift doesn't support pure virtual method, need to throw error
  71. func makeGestureRecognizer() -> UIGestureRecognizer {
  72. fatalError("This method must be overridden")
  73. }
  74. func shouldBeginProgress(for gestureRecognizer: UIGestureRecognizer) -> Bool {
  75. // return true by default
  76. return true
  77. }
  78. func calculateProgress(for gestureRecognizer: UIGestureRecognizer) -> (progress: CGFloat, shouldFinishInteractiveTransition: Bool) {
  79. fatalError("This method must be overridden")
  80. }
  81. }