CoverAnimator.swift 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. //
  2. // Created by Tom Baranes on 16/07/16.
  3. // Copyright © 2016 Jake Lin. All rights reserved.
  4. //
  5. import UIKit
  6. public class CoverAnimator: NSObject, AnimatedPresenting {
  7. // MARK: - AnimatedPresenting
  8. public var transitionDuration: Duration = defaultTransitionDuration
  9. // MARK: - private
  10. fileprivate var direction: TransitionAnimationType.Direction
  11. public init(from direction: TransitionAnimationType.Direction, duration: Duration) {
  12. self.direction = direction
  13. self.transitionDuration = duration
  14. super.init()
  15. }
  16. }
  17. // MARK: - Animator
  18. extension CoverAnimator: UIViewControllerAnimatedTransitioning {
  19. public func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
  20. return retrieveTransitionDuration(transitionContext: transitionContext)
  21. }
  22. public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
  23. let (fromView, toView, tempContainerView) = retrieveViews(transitionContext: transitionContext)
  24. let isPresenting = self.isPresenting(transitionContext: transitionContext)
  25. guard let containerView = tempContainerView, let animatingView = isPresenting ? toView : fromView else {
  26. transitionContext.completeTransition(true)
  27. return
  28. }
  29. let finalFrame: CGRect
  30. if isPresenting {
  31. finalFrame = getFinalFrame(from: direction, initialFrame: animatingView.frame, containerFrame: containerView.frame)
  32. containerView.addSubview(animatingView)
  33. } else {
  34. // Animate back to origin when dismiss the modal
  35. let oppositeDirection = direction.opposite
  36. finalFrame = getFinalFrame(from: oppositeDirection, initialFrame: animatingView.frame, containerFrame: containerView.frame)
  37. }
  38. animateCover(animatingView: animatingView, finalFrame: finalFrame) {
  39. if !isPresenting {
  40. fromView?.removeFromSuperview()
  41. }
  42. transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
  43. }
  44. }
  45. }
  46. // MARK: - Helper
  47. private extension CoverAnimator {
  48. func getFinalFrame(from direction: TransitionAnimationType.Direction, initialFrame: CGRect, containerFrame: CGRect) -> CGRect {
  49. var initialFrame = initialFrame
  50. switch direction {
  51. case .right:
  52. initialFrame.origin.x = 0 - initialFrame.size.width
  53. case .left:
  54. initialFrame.origin.x = containerFrame.size.width + initialFrame.size.width
  55. case .top:
  56. initialFrame.origin.y = containerFrame.size.height + initialFrame.size.height
  57. case .bottom:
  58. initialFrame.origin.y = 0 - initialFrame.size.height
  59. default:
  60. fatalError("Invalid cover direction")
  61. }
  62. return initialFrame
  63. }
  64. }
  65. // MARK: - Animation
  66. private extension CoverAnimator {
  67. func animateCover(animatingView: UIView, finalFrame: CGRect, completion: @escaping AnimatableCompletion) {
  68. UIView.animate(withDuration: transitionDuration, animations: {
  69. animatingView.frame = finalFrame
  70. }, completion: { _ in
  71. completion()
  72. })
  73. }
  74. }