Last active
November 7, 2023 01:28
-
-
Save andyyhope/e6318b1735a4fb85e6a61762ec46c8ba to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: | |
//: UIView Animation Syntax Sugar | |
//: | |
//: Created by Andyy Hope on 18/08/2016. | |
//: Twitter: @andyyhope | |
//: Medium: Andyy Hope, https://medium.com/@AndyyHope | |
import UIKit | |
extension UIView { | |
class Animator { | |
typealias Completion = (Bool) -> Void | |
typealias Animations = () -> Void | |
private var animations: Animations | |
private var completion: Completion? | |
private let duration: TimeInterval | |
private let delay: TimeInterval | |
private let options: UIViewAnimationOptions | |
init(duration: TimeInterval, delay: TimeInterval = 0, options: UIViewAnimationOptions = []) { | |
class Animator { | |
typealias Completion = (Bool) -> Void | |
typealias Animations = () -> Void | |
fileprivate var animations: Animations | |
fileprivate var completion: Completion? | |
fileprivate let duration: TimeInterval | |
fileprivate let delay: TimeInterval | |
fileprivate let options: UIViewAnimationOptions | |
init(duration: TimeInterval, delay: TimeInterval = 0, options: UIViewAnimationOptions = []) { | |
self.animations = {} | |
self.completion = nil | |
self.duration = duration | |
self.delay = delay | |
self.options = options | |
} | |
func animations(_ animations: @escaping Animations) -> Self { | |
self.animations = animations | |
return self | |
} | |
func completion(_ completion: @escaping Completion) -> Self { | |
self.completion = completion | |
return self | |
} | |
func animate() { | |
UIView.animate(withDuration: duration, delay: delay, animations: animations, completion: completion) | |
} | |
} | |
final class SpringAnimator: Animator { | |
fileprivate let damping: CGFloat | |
fileprivate let velocity: CGFloat | |
init(duration: TimeInterval, delay: TimeInterval = 0, damping: CGFloat, velocity: CGFloat, options: UIViewAnimationOptions = []) { | |
self.damping = damping | |
self.velocity = velocity | |
super.init(duration: duration, delay: delay, options: options) | |
} | |
override func animate() { | |
UIView.animate(withDuration: duration, delay: delay, usingSpringWithDamping: damping, initialSpringVelocity: velocity, options: options, animations: animations, completion: completion) | |
} | |
} | |
} | |
// MARK: - Example API | |
var view = UIView(frame: .zero) | |
// Regular Animations | |
UIView.Animator(duration: 0.3) | |
.animations { | |
view.frame.size.height = 100 | |
view.frame.size.width = 100 | |
} | |
.completion { finished in | |
view.backgroundColor = .black | |
} | |
.animate() | |
// Regular Animations with options | |
UIView.Animator(duration: 0.4, delay: 0.2) | |
.animations { } | |
.completion { _ in } | |
.animate() | |
UIView.Animator(duration: 0.4, options: [.autoreverse, .curveEaseIn]) | |
.animations { } | |
.completion { _ in } | |
.animate() | |
UIView.Animator(duration: 0.4, delay: 0.2, options: [.autoreverse, .curveEaseIn]) | |
.animations { } | |
.completion { _ in } | |
.animate() | |
// Spring Animator | |
UIView.SpringAnimator(duration: 0.3, delay: 0.2, damping: 0.2, velocity: 0.2, options: [.autoreverse, .curveEaseIn]) | |
.animations { } | |
.completion { _ in } | |
.animate() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
That's a much nicer interface to the existing UIView animations api, you did an awesome job.
I updated some existing code after looking at what you have done and the result is:
I like to have the
enum
instead of subclasses of the animator. This way the animator itself works like a single interface for a factory of animations. Theenum
can also be extended to allow, for example, the setup of animations usingCATransaction
s if you want to specify a custom timing function.