Skip to content

Commit

Permalink
Added onStopped() modifier function
Browse files Browse the repository at this point in the history
  • Loading branch information
PimCoumans committed Apr 17, 2024
1 parent 20a464d commit 2f1e85b
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 8 deletions.
28 changes: 24 additions & 4 deletions Sources/AnimationPlanner/Animations/Animate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public struct Animate: Animation, SequenceAnimatable, GroupAnimatable {
public internal(set) var timingFunction: CAMediaTimingFunction?

/// Class that holds stopped state
private let stopper: Stopper
internal let stopper: Stopper

/// Creates a new animation, animating the properties updated in the ``changes`` closure
///
Expand All @@ -32,15 +32,22 @@ public struct Animate: Animation, SequenceAnimatable, GroupAnimatable {
self.duration = duration
self.timingFunction = timingFunction
self.changes = { [weak stopper] in
guard stopper?.isStopped == false else { return }
guard stopper?.isStopped == false else {
return
}
stopper?.isRunning = true
changes()
}
self.stopper = stopper
}
}

internal class Stopper {
var isStopped: Bool = false
extension Animate {
internal class Stopper {
var isRunning: Bool = false
var isStopped: Bool = false
var stopHandler: (() -> Void)?
}
}

extension Animate: PerformsAnimations {
Expand Down Expand Up @@ -70,6 +77,19 @@ extension Animate: PerformsAnimations {
}

public func stop() {
if stopper.isRunning {
UIView.animate(
withDuration: 0,
delay: 0,
options: [
.beginFromCurrentState,
.overrideInheritedDuration,
.overrideInheritedOptions
],
animations: changes
)
}
stopper.stopHandler?()
stopper.isStopped = true
}
}
21 changes: 17 additions & 4 deletions Sources/AnimationPlanner/Protocols/AnimationModifiers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,20 @@ public protocol AnimationModifiers: Animation {
///
/// - Important: Timing functions are ignored when applied to an animation using spring interpolation (``AnimateSpring``)
///
/// - Parameter function: Custom CAMediaTimingFunction or any of the avaialble static extensions
/// - Parameter function: Custom CAMediaTimingFunction or any of the available static extensions
func timingFunction(_ function: CAMediaTimingFunction) -> Self

/// Sets the ``Animation/changes`` to be performed for your animation. Could be used when it‘s convenient to add your animation changes at a later state, e.g., after applying other modifiers to your ``Animate`` struct.
/// - Parameter changes: Change properties to animate in this closure
/// - Note: This replaces any previous animation changes set
func changes(_ changes: @escaping () -> Void) -> Self

/// Adds a handler to be called when the animation is stopped. This handler is only called for the animations that are currently being run.
///
/// Calling `view.layer.removeAllAnimations()` immediately stops animations for all views updated with this animation,
/// - Parameter stopHandler: Closure called when animation is stopped
/// - Note: This method is only useful for long-running or repeating animations, as these are usually not stopped by stopping the running sequence.
func onStopped(_ stopHandler: @escaping () -> Void) -> Self
}

extension Animate: AnimationModifiers {
Expand All @@ -48,6 +55,9 @@ extension Animate: AnimationModifiers {
public func changes(_ changes: @escaping () -> Void) -> Animate {
mutate { $0.changes = changes }
}
public func onStopped(_ stopHandler: @escaping () -> Void) -> Animate {
mutate { $0.stopper.stopHandler = stopHandler }
}
}

// MARK: - Spring modifiers
Expand Down Expand Up @@ -127,9 +137,6 @@ extension Extra: Mutable { }

extension AnimateSpring: Mutable { }
extension AnimateSpring: AnimationModifiers where Contained: AnimationModifiers {
func modifyAnimation(_ handler: (AnimationModifiers) -> Contained) -> Self {
mutate { $0.animation = handler(animation) }
}
public func options(_ options: UIView.AnimationOptions) -> Self {
mutate { $0.animation = animation.options(options) }
}
Expand All @@ -142,6 +149,9 @@ extension AnimateSpring: AnimationModifiers where Contained: AnimationModifiers
public func changes(_ changes: @escaping () -> Void) -> Self {
mutate { $0.animation = animation.changes(changes) }
}
public func onStopped(_ stopHandler: @escaping () -> Void) -> AnimateSpring<Springed> {
mutate { $0.animation = animation.onStopped(stopHandler) }
}
}

extension AnimateDelayed: Mutable { }
Expand All @@ -158,4 +168,7 @@ extension AnimateDelayed: AnimationModifiers where Contained: Animation & Animat
public func changes(_ changes: @escaping () -> Void) -> Self {
mutate { $0.animation = animation.changes(changes) }
}
public func onStopped(_ stopHandler: @escaping () -> Void) -> AnimateDelayed<Delayed> {
mutate { $0.animation = animation.onStopped(stopHandler) }
}
}

0 comments on commit 2f1e85b

Please sign in to comment.