Skip to content

Instantly share code, notes, and snippets.

@rolandleth
Last active September 15, 2022 17:39
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rolandleth/421dcde6757b942ac7102fea435fd3c3 to your computer and use it in GitHub Desktop.
Save rolandleth/421dcde6757b942ac7102fea435fd3c3 to your computer and use it in GitHub Desktop.
import UIKit
import PlaygroundSupport
let touchAnimationDuration: TimeInterval = 0.3
var shouldPulse = true
class Handler {
@objc
func didTouchUpInside(_ button: UIButton) {
shouldPulse = true
pulse(button)
}
@objc
func flashButton() {
flashButtonBackground()
}
@objc
func didTouch(_ button: UIButton) {
shouldPulse = false
button.backgroundColor = .clear
button.layer.borderWidth = 1
let animation = CABasicAnimation(keyPath: "borderWidth")
animation.fromValue = 1.5
animation.toValue = 1
animation.duration = touchAnimationDuration
button.layer.add(animation, forKey: "borderWidthIncrease")
UIView.animate(withDuration: touchAnimationDuration) {
button.transform = CGAffineTransform(scaleX: 0.95, y: 0.95)
}
}
@objc
func didLift(_ button: UIButton) {
button.layer.borderWidth = 1.5
let animation = CABasicAnimation(keyPath: "borderWidth")
animation.fromValue = 1
animation.toValue = 1.5
animation.duration = touchAnimationDuration
button.layer.add(animation, forKey: "borderWidthDecrease")
UIView.animate(withDuration: touchAnimationDuration) {
button.transform = .identity
}
}
}
let handler = Handler()
let view = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
view.backgroundColor = .white
let button = UIButton(type: .custom)
view.addSubview(button)
let tap = UITapGestureRecognizer(target: handler, action: #selector(handler.flashButton))
view.addGestureRecognizer(tap)
button.frame = CGRect(x: 40, y: 30, width: 120, height: 40)
button.setTitle("Tap me", for: .normal)
button.setTitleColor(.blue, for: .normal)
button.layer.borderWidth = 1.5
button.layer.borderColor = UIColor.blue.cgColor
button.layer.cornerRadius = 8
button.addTarget(handler, action: #selector(handler.didTouch), for: .touchDown)
button.addTarget(handler, action: #selector(handler.didTouchUpInside), for: .touchUpInside)
button.addTarget(handler, action: #selector(handler.didLift), for: .touchUpInside)
button.addTarget(handler, action: #selector(handler.didLift), for: .touchUpOutside)
// pulse(button)
PlaygroundPage.current.liveView = view
PlaygroundPage.current.needsIndefiniteExecution = true
func pulse(_ button: UIButton) {
let breatheDuration: TimeInterval = 1.8
let pauseDuration: TimeInterval = 1.2
let increaseAnimator = UIViewPropertyAnimator(duration: breatheDuration, curve: .easeOut) {
button.alpha = 1
button.backgroundColor = UIColor.blue.withAlphaComponent(0.07)
button.transform = CGAffineTransform(scaleX: 1.05, y: 1.05)
}
let decreaseAnimator = UIViewPropertyAnimator(duration: breatheDuration, curve: .easeOut) {
button.alpha = 0.8
button.backgroundColor = .clear
button.transform = CGAffineTransform(scaleX: 0.95, y: 0.95)
}
increaseAnimator.addCompletion { _ in
DispatchQueue.main.asyncAfter(deadline: .now() + pauseDuration) {
decreaseAnimator.startAnimation()
}
}
decreaseAnimator.addCompletion { _ in
guard shouldPulse else { return }
DispatchQueue.main.asyncAfter(deadline: .now() + pauseDuration) {
pulse(button)
}
}
increaseAnimator.startAnimation()
}
func flashButtonBackground() {
let animationDuration: TimeInterval = 0.2
let animatorIn = UIViewPropertyAnimator(duration: animationDuration, curve: .easeOut) {
button.backgroundColor = UIColor.black.withAlphaComponent(0.25)
}
let animatorOut = UIViewPropertyAnimator(duration: animationDuration, curve: .easeOut) {
button.backgroundColor = .white
}
animatorIn.addCompletion { _ in
animatorOut.startAnimation()
}
animatorIn.startAnimation()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment