我正在将一个新的文本值设置为 UILabel。目前,新文本看起来还不错。但是,我希望在新文本出现时添加一些动画。我想知道我能做些什么来使新文本的外观生动起来。
UILabel
下面是使这个工作的代码。
[UIView beginAnimations:@"animateText" context:nil]; [UIView setAnimationCurve:UIViewAnimationCurveEaseIn]; [UIView setAnimationDuration:1.0f]; [self.lbl setAlpha:0]; [self.lbl setText:@"New Text"; [self.lbl setAlpha:1]; [UIView commitAnimations];
自从 iOS4以来,它显然可以通过块来实现:
[UIView animateWithDuration:1.0 animations:^{ label.alpha = 0.0f; label.text = newText; label.alpha = 1.0f; }];
为了实现 没错交叉溶解转换(旧标签淡出 同时新标签淡入) ,您不希望淡出到不可见。会导致 即使文本没有改变,也会出现不必要的闪烁。
使用以下方法:
CATransition *animation = [CATransition animation]; animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; animation.type = kCATransitionFade; animation.duration = 0.75; [aLabel.layer addAnimation:animation forKey:@"kCATransitionFade"]; // This will fade: aLabel.text = "New"
参见: 在两个数字之间动画 UILabel 文本?
IOS10,9,8的演示:
在 IOS10至8.0上用 Xcode 8.2.1 & 7.1和 目标 C测试。
扣下载完整的项目,搜索 快速食谱中的 SO-3073520。
我想知道它是否有效,而且它完全有效!
目标 C
[UIView transitionWithView:self.label duration:0.25f options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ self.label.text = rand() % 2 ? @"Nice nice!" : @"Well done!"; } completion:nil];
斯威夫特345
UIView.transition(with: label, duration: 0.25, options: .transitionCrossDissolve, animations: { [weak self] in self?.label.text = (arc4random()() % 2 == 0) ? "One" : "Two" }, completion: nil)
淡化 UILabel (或任何 UIView)的正确方法是使用 Core Animation Transition。这不会闪烁,也不会褪色为黑色,如果内容是不变的。
Core Animation Transition
一个可移植且干净的解决方案是在 Swift 中使用 Extension(调用之前更改的可见元素)
Extension
// Usage: insert view.fadeTransition right before changing content extension UIView { func fadeTransition(_ duration:CFTimeInterval) { let animation = CATransition() animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut) animation.type = CATransitionType.fade animation.duration = duration layer.add(animation, forKey: CATransitionType.fade.rawValue) } }
调用看起来像这样:
// This will fade aLabel.fadeTransition(0.4) aLabel.text = "text"
在 GitHub上找到这个解决方案,在 快速食谱上找到更多细节。
Swift 2.0:
UIView.transitionWithView(self.view, duration: 1.0, options: UIViewAnimationOptions.TransitionCrossDissolve, animations: { self.sampleLabel.text = "Animation Fade1" }, completion: { (finished: Bool) -> () in self.sampleLabel.text = "Animation Fade - 34" })
或者
UIView.animateWithDuration(0.2, animations: { self.sampleLabel.alpha = 1 }, completion: { (value: Bool) in self.sampleLabel.alpha = 0.2 })
如果您想在 Swift中延迟这样做,请尝试这样做:
Swift
delay(1.0) { UIView.transitionWithView(self.introLabel, duration: 0.25, options: [.TransitionCrossDissolve], animations: { self.yourLabel.text = "2" }, completion: { finished in self.delay(1.0) { UIView.transitionWithView(self.introLabel, duration: 0.25, options: [.TransitionCrossDissolve], animations: { self.yourLabel.text = "1" }, completion: { finished in }) } }) }
使用@matt-https://stackoverflow.com/a/24318861/1982051创建的以下函数:
func delay(delay:Double, closure:()->()) { dispatch_after( dispatch_time( DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)) ), dispatch_get_main_queue(), closure) }
在 Swift 3中会变成这样
func delay(_ delay:Double, closure:()->()) { let when = DispatchTime.now() + delay DispatchQueue.main.after(when: when, execute: closure) }
这是一个基于@SwiftArchitect 代码的 C # UIView 扩展方法。当涉及到自动布局并且控件需要根据标签的文本移动时,这个调用代码使用标签的 Superview 作为转换视图,而不是标签本身。我为该操作添加了一个 lambda 表达式,以使其更加封装。
public static void FadeTransition( this UIView AView, double ADuration, Action AAction ) { CATransition transition = new CATransition(); transition.Duration = ADuration; transition.TimingFunction = CAMediaTimingFunction.FromName( CAMediaTimingFunction.Linear ); transition.Type = CATransition.TransitionFade; AView.Layer.AddAnimation( transition, transition.Type ); AAction(); }
通话代码:
labelSuperview.FadeTransition( 0.5d, () => { if ( condition ) label.Text = "Value 1"; else label.Text = "Value 2"; } );
使用 Swift 5,您可以选择以下两个 Playground 代码示例中的一个,以便通过一些交叉溶解动画来动画 UILabel的文本更改。
UIView
transition(with:duration:options:animations:completion:)
import UIKit import PlaygroundSupport class ViewController: UIViewController { let label = UILabel() override func viewDidLoad() { super.viewDidLoad() label.text = "Car" view.backgroundColor = .white view.addSubview(label) label.translatesAutoresizingMaskIntoConstraints = false label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true label.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true let tapGesture = UITapGestureRecognizer(target: self, action: #selector(toggle(_:))) view.addGestureRecognizer(tapGesture) } @objc func toggle(_ sender: UITapGestureRecognizer) { let animation = { self.label.text = self.label.text == "Car" ? "Plane" : "Car" } UIView.transition(with: label, duration: 2, options: .transitionCrossDissolve, animations: animation, completion: nil) } } let controller = ViewController() PlaygroundPage.current.liveView = controller
CATransition
CALayer
add(_:forKey:)
import UIKit import PlaygroundSupport class ViewController: UIViewController { let label = UILabel() let animation = CATransition() override func viewDidLoad() { super.viewDidLoad() label.text = "Car" animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut) // animation.type = CATransitionType.fade // default is fade animation.duration = 2 view.backgroundColor = .white view.addSubview(label) label.translatesAutoresizingMaskIntoConstraints = false label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true label.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true let tapGesture = UITapGestureRecognizer(target: self, action: #selector(toggle(_:))) view.addGestureRecognizer(tapGesture) } @objc func toggle(_ sender: UITapGestureRecognizer) { label.layer.add(animation, forKey: nil) // The special key kCATransition is automatically used for transition animations label.text = label.text == "Car" ? "Plane" : "Car" } } let controller = ViewController() PlaygroundPage.current.liveView = controller
Swift 4.2版本的 SwiftArchitect 解决方案(非常棒) :
祈求:
Swift 4.2解决方案(采用4.0解决方案并更新要编译的新枚举)
extension UIView { func fadeTransition(_ duration:CFTimeInterval) { let animation = CATransition() animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut) animation.type = CATransitionType.fade animation.duration = duration layer.add(animation, forKey: CATransitionType.fade.rawValue) } } func updateLabel() { myLabel.fadeTransition(0.4) myLabel.text = "Hello World" }
还有一个办法可以实现这一点。它被描述为 给你。这个想法是通过以下方式对 UILabel进行子类化,并覆盖 action(for:forKey:)功能:
action(for:forKey:)
class LabelWithAnimatedText: UILabel { override var text: String? { didSet { self.layer.setValue(self.text, forKey: "text") } } override func action(for layer: CALayer, forKey event: String) -> CAAction? { if event == "text" { if let action = self.action(for: layer, forKey: "backgroundColor") as? CAAnimation { let transition = CATransition() transition.type = kCATransitionFade //CAMediatiming attributes transition.beginTime = action.beginTime transition.duration = action.duration transition.speed = action.speed transition.timeOffset = action.timeOffset transition.repeatCount = action.repeatCount transition.repeatDuration = action.repeatDuration transition.autoreverses = action.autoreverses transition.fillMode = action.fillMode //CAAnimation attributes transition.timingFunction = action.timingFunction transition.delegate = action.delegate return transition } } return super.action(for: layer, forKey: event) } }
用法例子:
// do not forget to set the "Custom Class" IB-property to "LabelWithAnimatedText" // @IBOutlet weak var myLabel: LabelWithAnimatedText! // ... UIView.animate(withDuration: 0.5) { myLabel.text = "I am animated!" }
myLabel.text = "I am not animated!"
UILabel 扩展解决方案
extension UILabel{ func animation(typing value:String,duration: Double){ let characters = value.map { $0 } var index = 0 Timer.scheduledTimer(withTimeInterval: duration, repeats: true, block: { [weak self] timer in if index < value.count { let char = characters[index] self?.text! += "\(char)" index += 1 } else { timer.invalidate() } }) } func textWithAnimation(text:String,duration:CFTimeInterval){ fadeTransition(duration) self.text = text } //followed from @Chris and @winnie-ru func fadeTransition(_ duration:CFTimeInterval) { let animation = CATransition() animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut) animation.type = CATransitionType.fade animation.duration = duration layer.add(animation, forKey: CATransitionType.fade.rawValue) } }
通过 简单调用函数
uiLabel.textWithAnimation(text: "text you want to replace", duration: 0.2)
谢谢你们提供的所有建议,希望对我们的长远发展有所帮助
动画的 duration和 timingFunction属性可以省略,在这种情况下,它们将分别获取其默认值 0.25和 .curveEaseInEaseOut。
duration
timingFunction
0.25
.curveEaseInEaseOut
let animation = CATransition() label.layer.add(animation, forKey: nil) label.text = "New text"
和写这个是一样的:
let animation = CATransition() animation.duration = 0.25 animation.timingFunction = .curveEaseInEaseOut label.layer.add(animation, forKey: nil) label.text = "New text"