简体   繁体   English

使用 UIViewPropertyAnimator 为 UILabel textColor 属性设置动画

[英]Animating UILabel textColor property with UIViewPropertyAnimator

I have a question which seems simple but I found no solution yet.我有一个看起来很简单的问题,但我还没有找到解决方案。

I animate a view with labels inside using UIViewPropertyAnimator and a slider to manually adjust the animator's fractionComplete property.我使用UIViewPropertyAnimator和 slider 为带有标签的视图设置动画,以手动调整动画器的fractionComplete属性。

Inside the view I animate I have a UILabel and I want to animate its textColor .在我动画的视图中,我有一个 UILabel 并且我想动画它的textColor

I found SO answers suggesting to animate the textColor like this:我发现SO 答案建议像这样为textColor设置动画:

UIView.transition(with: yourLabel, duration: 0.3, options: .transitionCrossDissolve, animations: {
  self.yourLabel.textColor = .red
}, completion: nil)

However, for me this does not work, becuase I want the animation to proceed depending on the fractionComplete I set for the animator.但是,对我来说这不起作用,因为我希望 animation 根据我为动画师设置的fractionComplete继续。

As said in the comments, the textColor property can not be animated.正如评论中所说, textColor属性不能动画。 However, there is a technique called color interpolation, which might be a nice workaround.但是,有一种称为颜色插值的技术,它可能是一个很好的解决方法。

You can find multiple ways to solve this in this thread , however, I provide you with one solution also:您可以在此线程中找到多种解决此问题的方法,但是,我也为您提供了一种解决方案:

extension UIColor {
var components: (r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat) {
    let components = self.cgColor.components!

    switch components.count == 2 {
    case true : 
        return (r: components[0], g: components[0], b: components[0], a: components[1])
    case false: 
        return (r: components[0], g: components[1], b: components[2], a: components[3])
    }
}

static func interpolate(from fromColor: UIColor, to toColor: UIColor, with progress: CGFloat) -> UIColor {
    let fromComponents = fromColor.components
    let toComponents = toColor.components
    
    let r = (1 - progress) * fromComponents.r + progress * toComponents.r
    let g = (1 - progress) * fromComponents.g + progress * toComponents.g
    let b = (1 - progress) * fromComponents.b + progress * toComponents.b
    let a = (1 - progress) * fromComponents.a + progress * toComponents.a
    
    return UIColor(red: r, green: g, blue: b, alpha: a)
}
}

Then, all you have to do is this in the function you call when the slider's value has changed:然后,您只需在滑块值更改时调用的 function 中执行此操作:

@objc func sliderChanged(_ sender: UISlider) {
     animator.fractionComplete = CGFloat(sender.value)
     yourLabel.textColor = UIColor.interpolate(from: fromColor, to: toColor, with: sender.value)
}

You are not animating the textColor , rather you change it to a different color with each call to sliderChanged , but the change appears gradual and does not jump from your start color to your second color, so I think it should achieve your desired result.您不是在为textColor设置动画,而是在每次调用sliderChanged时将其更改为不同的颜色,但是这种变化看起来是渐进的,并且不会从您的起始颜色跳到您的第二种颜色,所以我认为它应该达到您想要的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM