如何为UILabel的textColor属性添加动画效果?

91

由于某些原因,当我尝试对textColor进行动画效果时,它不能正常工作。 textColor 突然从 A 变成了 B。是否可能将其动画效果,例如从红色到黑色?

11个回答

210

相反,你是否尝试在对象本身上使用交叉淡入淡出的过渡效果,像这样,它将为你提供一个漂亮的从一种颜色到另一种颜色的淡入淡出效果:

Objective C

[UIView transitionWithView:myLabel duration:0.25 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
    myLabel.textColor = NEW_COLOR;
} completion:^(BOOL finished) {
}];

Swift 5

UIView.transition(with: creditsLabel, duration: 0.25, options: .transitionCrossDissolve) {
    self.creditsLabel.textColor = .red
}

出于多种原因,这比使用NSTimers、CATextLayers等更好。 CATextLayer不支持适当的文本字间距或NSAttributedText,而NSTimers有延迟(还有太多代码)。 上面的过渡动画就解决了这个问题,并且也可以用作链式动画。 我也遇到了同样的问题,已经尝试过上述解决方案,但是这个简单的代码却奏效。


7
好的,优雅的,实际上是最好和最简洁的解决方案。 - maksa
19
太好了,Swift语言下同样适用:UIView.transitionWithView(creditsLabel, duration: 0.3, options: .TransitionCrossDissolve, animations: { self.creditsLabel.textColor = UIColor.redColor() }, completion: nil) - SimplGy
13
注意:这仅适用于标签是静态的情况。如果您这样做并且标签的位置正在被修改,则淡出动画将显示不美观的瑕疵。 - Lukas Petr
在我的Xcode 10.2.1和Swift 5上无法工作。下面的'shokaveli'方法可以。 - Martin
我一直在寻找在SwiftUI中实现这个的方法,但目前看来似乎不支持。 - philipp

62

Swift 4解决方案:

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

请注意,这仅适用于 with 属性具有 UILabel 实例的情况。如果您执行类似于 transition(with: outerView.label…) 的操作并尝试在其中设置它,则会静默失败。 - Sam Soffes
由于某些原因,它对我不起作用。在动画期间,它突然进行了更改而不是逐渐进行。 :( - ScottyBlades
1
@ScottyBlades 也许你正在后台线程上执行动画?试着将 UIView.transition 代码包裹在 DispatchQueue.main.async {} 括号中。 - budiDino
1
第一次尝试没有成功,原因是我使用了 options: .easeInOut,所以我将其更改为 .transitionCrossDissolve 就可以了。 - LeoGalante

13

textColor不可动画化的原因是UILabel使用普通的CALayer而非CATextLayer。

为了使textColor(以及文本、字体等)可动画化,我们可以子类化UILabel并使其使用CATextLayer。

这需要相当多的工作,但幸运的是我已经完成了它 :-)。

您可以在文章中找到完整的解释和一个可替换UILabel的开源组件。


9

这是唯一对我有效的方法:

let changeColor = CATransition()
changeColor.duration = 1

CATransaction.begin()

CATransaction.setCompletionBlock {
    selected.label.layer.add(changeColor, forKey: nil)
    selected.label.textColor = .black
}

selected.nameLabel.textColor = .red

CATransaction.commit()

有人明白这是如何/为什么工作的吗?或者具体来说,为什么CATransition似乎只在CATransaction的完成块内起作用? - The Way

9

您可以尝试创建另一个UILabel实例或具有textColor的其他实例,然后在这两个实例之间应用动画(旧textColor和新textColor的实例)。


6
这是我用来动画化标签文本颜色的代码。 重要的部分是在动画之前将textColor设置为clearColor
label.textColor = [UIColor clearColor];
[UIView transitionWithView:label duration:duration/4 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
    label.textColor = self.highlightedCellPrimaryTextColor;
} completion:^(BOOL finished) { }];

6
这个答案已经过时,不是原问题的好解决方案。@strange在下面提供的答案更好,应该使用它来代替这个答案:https://dev59.com/jHE95IYBdhLWcg3wKqyq#20892927 //以下是旧答案
文档中未指定textColor属性为可动画属性,因此我认为你不能使用简单的UIView动画块来实现它...
这可能可以通过一个NSTimer每隔几毫秒触发一次,每次逐渐设置颜色来粗略地完成。
我说这很粗糙,因为它需要一个预设颜色值的数组或其他容器,从起始颜色到终止颜色,我相信有一种方法可以使用核心动画或其他东西来实现这一点,只是我不知道是什么。

一个函数,可以抛出在给定百分比下介于A和B之间的RGB值数组。不过我对颜色算法一无所知。 - dontWatchMyProfile
这里有很好的解决方法:这里这里感谢安娜·卡列尼娜。 - jackal
4
为了手动驱动动画,您应该使用CADisplayLink而不是NSTimer,因为它与显示更新同步。请参阅WWDC 2014 会议第236节:构建可中断和响应的交互,大约在13:00左右。 - Douglas Hill
请注意:即使在过去这是正确的,但现在不应再接受此答案。 - bitwit
1
Stack Overflow不允许我删除这个过时的答案,因为它已经被接受了。请查看下面@strange的答案。 - Jasarien

0

尝试使用核心动画

   func textColorBlinking(){
        let changeColor = CATransition()
        changeColor.duration = 1
        changeColor.type = .fade
        changeColor.repeatCount = Float.infinity
        CATransaction.begin()
        CATransaction.setCompletionBlock {
            self.lblHome.layer.add(changeColor, forKey: nil)
            self.lblHome.textColor = .white
        }
        self.lblHome.textColor = .red
        CATransaction.commit()
   }

0
我发现将一个UIView放置在标签下方并动画化其不透明度相当容易。 该标签必须添加到该视图中。 从资源消耗的角度来看,这可能不是一个好的解决方案,但非常直接。

0

感谢@Strange的回答,使用稍微改变语法后,在Swift 5和Xcode 11中完美运行。我正在为多个UILabel动画文本颜色,如果您也是这种情况,请尝试此方法。

for label in [label1, label2, ...] as [UILabel] { // loop through a @IBOutlet UILabel array
        UIView.transition(with: label, duration: 0.3, options: .transitionCrossDissolve, animations: {
            label.textColor = .label
        }, completion: nil)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接