I am trying to change a button\'s color (just a flash/blink) to green when a scan is correct and red when there\'s a problem. I am able to do this with a view like so
This should work in Swift 4
extension UIView{
func blink() {
self.alpha = 0.2
UIView.animate(withDuration: 1, delay: 0.0, options: [.curveLinear, .repeat, .autoreverse], animations: {self.alpha = 1.0}, completion: nil)
}
}
You can try something like this:
extension UIView {
func blink() {
UIView.animateWithDuration(0.5, //Time duration you want,
delay: 0.0,
options: [.CurveEaseInOut, .Autoreverse, .Repeat],
animations: { [weak self] in self?.alpha = 0.0 },
completion: { [weak self] _ in self?.alpha = 1.0 })
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,Int64(2 * NSEC_PER_SEC)),dispatch_get_main_queue()){
[weak self] in
self?.layer.removeAllAnimations()
}
}
}
//MARK : Usage
yourButton.flash()
extension UIButton {
func flash() {
let flash = CABasicAnimation(keyPath: "opacity")
flash.duration = 0.5
flash.fromValue = 1
flash.toValue = 0.1
flash.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
flash.autoreverses = true
flash.repeatCount = 3
layer.add(flash, forKey: nil)
}
}
Swift 3.0
func btnFlash_Clicked(sender: AnyObject) {
if !flashing{
callButton.alpha = 1.0
UIView.animate(withDuration: 0.5, delay: 0.0, options: [.allowUserInteraction], animations: {() -> Void in
callButton.alpha = 0.5
}, completion: {(finished: Bool) -> Void in
})
flashing = true
}
else{
flashing = false
callButton.alpha = 0.5
UIView.animate(withDuration: 0.5, delay: 0.0, options: [.allowUserInteraction], animations: {() -> Void in
callButton.alpha = 1.0
}, completion: {(finished: Bool) -> Void in
})
}
}
I've maked an extension with some useful options:
extension UIButton {
open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
return self.bounds.contains(point) ? self : nil
}
func blink(enabled: Bool = true, duration: CFTimeInterval = 1.0, stopAfter: CFTimeInterval = 0.0 ) {
enabled ? (UIView.animate(withDuration: duration, //Time duration you want,
delay: 0.0,
options: [.curveEaseInOut, .autoreverse, .repeat],
animations: { [weak self] in self?.alpha = 0.0 },
completion: { [weak self] _ in self?.alpha = 1.0 })) : self.layer.removeAllAnimations()
if !stopAfter.isEqual(to: 0.0) && enabled {
DispatchQueue.main.asyncAfter(deadline: .now() + stopAfter) { [weak self] in
self?.layer.removeAllAnimations()
}
}
}
}
First of all, I've overrided the hittest
function to enabling the touch also when the button have the alpha
equals to 0.0 (transparent) during the animation.
Then , all input vars have a default value so you can launch the blink()
method without parameters
I've introduced also the enabled
parameter to start or stop the animations on your button.
Finally, if you want you can stop animation after a specific time with the stopAfter
parameter.
yourButton.blink() // infinite blink effect with the default duration of 1 second
yourButton.blink(enabled:false) // stop the animation
yourButton.blink(duration: 2.0) // slowly the animation to 2 seconds
yourButton.blink(stopAfter:5.0) // the animation stops after 5 seconds.
Typical uses:
yourButton.blink(duration: 1.5, stopAfter:10.0)
// your code..
yourButton.blink()
// other code..
yourButton.blink(enabled:false)
I hope that will solve your problem.
buttonScan.alpha = 1.0
UIView.animate(withDuration: 1.0, delay: 1.0, options: UIView.AnimationOptions.curveEaseOut, animations: {
buttonScan.alpha = 0.0
}, completion: nil)