I want to flash my textColor
of UILabel
fromColor toColor, but I can not do it. Can you help me, here's what I've done :
extension UILabel {
func blinkTextColor(fromColor: UIColor, toColor: UIColor, duration: TimeInterval, completion: ((_ view: UIView) -> ())? = nil) {
UIView.animate(withDuration: duration, delay: 0.0, options: [.curveLinear, .repeat, .autoreverse, .allowUserInteraction], animations: {
self.textColor = fromColor
self.textColor = toColor
}, completion: { _ in
completion?(self)
})
}
}
It doesn't work.
You need to take two colours variables and swap them once animation finished and call the colour changing function recursively.
I answered once here Animate CAGradientLayer in Swift . It looks like same thing.
Although I tried and below is the code which worked for me.
For the convenience I created a custom class of UILabel
which can be use easily.
class BlinkLabel: UILabel, CAAnimationDelegate {
var colours: [UIColor] = []
var speed: Double = 1.0
fileprivate var shouldAnimate = true
fileprivate var currentColourIndex = 0
func startBlinking() {
if colours.count <= 1 {
/// Can not blink
return
}
shouldAnimate = true
currentColourIndex = 0
let toColor = self.colours[self.currentColourIndex]
animateToColor(toColor)
}
func stopBlinking() {
shouldAnimate = false
self.layer.removeAllAnimations()
}
fileprivate func animateToColor(_ color: UIColor) {
if !shouldAnimate {return}
let changeColor = CATransition()
changeColor.duration = speed
changeColor.type = .fade
changeColor.repeatCount = 1
changeColor.delegate = self
changeColor.isRemovedOnCompletion = true
CATransaction.begin()
CATransaction.setCompletionBlock {
self.layer.add(changeColor, forKey: nil)
self.textColor = color
}
CATransaction.commit()
}
// MARK:- CAAnimationDelegate
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
if flag {
if !self.shouldAnimate {return}
/// Calculating the next colour
self.currentColourIndex += 1
if self.currentColourIndex == self.colours.count {
self.currentColourIndex = 0
}
let toColor = self.colours[self.currentColourIndex]
/// You can remove this delay and directly call the function self.animateToColor(toColor) I just gave this to increase the visible time for each colour.
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2, execute: {
self.animateToColor(toColor)
})
}
}
}
Usage:
label.colours = [.red, .green, .blue, .orange]
label.speed = 1.0
label.startBlinking()
/// Stop after 10 seconds
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 10) {
self.label.stopBlinking()
}
You can animate label with multiple colours.
let changeColor = CATransition()
changeColor.duration = 1
changeColor.type = .fade
changeColor.repeatCount = Float.infinity
CATransaction.begin()
CATransaction.setCompletionBlock {
self.lbl.layer.add(changeColor, forKey: nil)
self.lbl.textColor = .green
}
self.lbl.textColor = .red
CATransaction.commit()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.