SwipeAnimator.swift 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. //
  2. // SwipeAnimator.swift
  3. //
  4. // Created by Jeremy Koch
  5. // Copyright © 2017 Jeremy Koch. All rights reserved.
  6. //
  7. import UIKit
  8. protocol SwipeAnimator {
  9. /// A Boolean value indicating whether the animation is currently running.
  10. var isRunning: Bool { get }
  11. /**
  12. The animation to be run by the SwipeAnimator
  13. - parameter animation: The closure to be executed by the animator
  14. */
  15. func addAnimations(_ animation: @escaping () -> Void)
  16. /**
  17. Completion handler for the animation that is going to be started
  18. - parameter completion: The closure to be execute on completion of the animator
  19. */
  20. func addCompletion(completion: @escaping (Bool) -> Void)
  21. /**
  22. Starts the defined animation
  23. */
  24. func startAnimation()
  25. /**
  26. Starts the defined animation after the given delay
  27. - parameter delay: Delay of the animation
  28. */
  29. func startAnimation(afterDelay delay: TimeInterval)
  30. /**
  31. Stops the animations at their current positions.
  32. - parameter withoutFinishing: A Boolean indicating whether any final actions should be performed.
  33. */
  34. func stopAnimation(_ withoutFinishing: Bool)
  35. }
  36. @available(iOS 10.0, *)
  37. extension UIViewPropertyAnimator: SwipeAnimator {
  38. func addCompletion(completion: @escaping (Bool) -> Void) {
  39. addCompletion { position in
  40. completion(position == .end)
  41. }
  42. }
  43. }
  44. class UIViewSpringAnimator: SwipeAnimator {
  45. var isRunning: Bool = false
  46. let duration:TimeInterval
  47. let damping:CGFloat
  48. let velocity:CGFloat
  49. var animations:(() -> Void)?
  50. var completion:((Bool) -> Void)?
  51. required init(duration: TimeInterval,
  52. damping: CGFloat,
  53. initialVelocity velocity: CGFloat = 0) {
  54. self.duration = duration
  55. self.damping = damping
  56. self.velocity = velocity
  57. }
  58. func addAnimations(_ animations: @escaping () -> Void) {
  59. self.animations = animations
  60. }
  61. func addCompletion(completion: @escaping (Bool) -> Void) {
  62. self.completion = { [weak self] finished in
  63. guard self?.isRunning == true else { return }
  64. self?.isRunning = false
  65. self?.animations = nil
  66. self?.completion = nil
  67. completion(finished)
  68. }
  69. }
  70. func startAnimation() {
  71. self.startAnimation(afterDelay: 0)
  72. }
  73. func startAnimation(afterDelay delay:TimeInterval) {
  74. guard let animations = animations else { return }
  75. isRunning = true
  76. UIView.animate(withDuration: duration,
  77. delay: delay,
  78. usingSpringWithDamping: damping,
  79. initialSpringVelocity: velocity,
  80. options: [.curveEaseInOut, .allowUserInteraction],
  81. animations: animations,
  82. completion: completion)
  83. }
  84. func stopAnimation(_ withoutFinishing: Bool) {
  85. isRunning = false
  86. }
  87. }