Animer un changement de texte dans UILabel
je mets une nouvelle valeur de texte à UILabel
. Actuellement, le nouveau texte apparaît très bien. Cependant, j'aimerais ajouter de l'animation lorsque le nouveau texte apparaît. Je me demande ce que je peux faire pour animer l'apparition du nouveau texte.
10 réponses
Objectif-C
pour obtenir une transition vraie Cross-dissolve (ancienne étiquette s'effaçant tandis que nouvelle étiquette s'efface), vous ne voulez pas de fondu à invisible. Il en résulterait scintillement indésirable, même si le texte est inchangé .
utilisez plutôt cette approche:
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"
Voir Aussi: animer UILabel texte entre deux numéros?
démonstration à iOS 10, 9, 8:
Testé avec Xcode 8.2.1 & 7.1 , Objectifec sur iOS 10 à 8.0 .
► pour télécharger le projet complet, recherchez SO-3073520 dans Swift Recettes .
je me demande si ça marche et si ça marche parfaitement!
Objectif-C
[UIView transitionWithView:self.label
duration:0.25f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
self.label.text = rand() % 2 ? @"Nice nice!" : @"Well done!";
} completion:nil];
Swift 3
UIView.transition(with: label,
duration: 0.25,
options: .transitionCrossDissolve,
animations: { [weak self] in
self?.label.text = (arc4random()() % 2 == 0) ? "One" : "Two"
}, completion: nil)
Swift 4
la bonne façon de faner un UILabel (ou tout UIView d'ailleurs) est d'utiliser un Core Animation Transition
. Cela ne clignotera pas, et ne se fondra pas en noir si le contenu est inchangé.
une solution portable et propre consiste à utiliser un Extension
dans Swift (invoquer un changement préalable d'éléments visibles)
// Usage: insert view.fadeTransition right before changing content
extension UIView {
func fadeTransition(_ duration:CFTimeInterval) {
let animation = CATransition()
animation.timingFunction = CAMediaTimingFunction(name:
kCAMediaTimingFunctionEaseInEaseOut)
animation.type = kCATransitionFade
animation.duration = duration
layer.add(animation, forKey: kCATransitionFade)
}
}
l'Invocation ressemble à ceci:
// This will fade
aLabel.fadeTransition(0.4)
aLabel.text = "text"
► trouvez cette solution sur Github et des détails supplémentaires sur recettes Swift .
depuis iOS4 il peut évidemment être fait avec des blocs:
[UIView animateWithDuration:1.0
animations:^{
label.alpha = 0.0f;
label.text = newText;
label.alpha = 1.0f;
}];
voici le code pour que ça marche.
[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];
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"
})
ou
UIView.animateWithDuration(0.2, animations: {
self.sampleLabel.alpha = 1
}, completion: {
(value: Bool) in
self.sampleLabel.alpha = 0.2
})
c'est une méthode d'extension C# UIView basée sur le code de @SwiftArchitect. Lorsque la mise en page automatique est impliquée et que les commandes doivent se déplacer en fonction du texte de l'étiquette, ce code d'appel utilise la Superview de l'étiquette comme vue de transition au lieu de l'étiquette elle-même. J'ai ajouté une expression lambda pour l'action pour la rendre plus encapsulé.
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();
}
code D'appel:
labelSuperview.FadeTransition( 0.5d, () =>
{
if ( condition )
label.Text = "Value 1";
else
label.Text = "Value 2";
} );
si vous voulez faire ceci dans Swift
avec un retard essayez ceci:
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
})
}
})
}
utilisant la fonction suivante créée par @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)
}
qui deviendra ceci dans Swift 3
func delay(_ delay:Double, closure:()->()) {
let when = DispatchTime.now() + delay
DispatchQueue.main.after(when: when, execute: closure)
}
selon vos goûts et vos besoins, vous pouvez choisir l'un des trois extraits de code suivants afin d'animer vos modifications de texte UILabel
avec un peu d'animation Cross dissolve:
1. Utilisation transition(with:duration:options:animations:completion:)
import UIKit
import PlaygroundSupport
class ViewController: UIViewController {
let label: UILabel = {
"151900920".frame.origin = CGPoint(x: 50, y: 50)
"151900920".text = "Bob"
"151900920".sizeToFit()
return "151900920"
}(UILabel())
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
view.addSubview(label)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(toggle(_:)))
view.addGestureRecognizer(tapGesture)
}
func toggle(_ sender: UITapGestureRecognizer) {
let animation = {
self.label.text = self.label.text == "Bob" ? "Dan" : "Bob"
}
UIView.transition(with: label, duration: 1, options: .transitionCrossDissolve, animations: animation, completion: nil)
}
}
let controller = ViewController()
PlaygroundPage.current.liveView = controller
2. En utilisant CATransition
et CATransition
's type
biens
import UIKit
import PlaygroundSupport
class ViewController: UIViewController {
let label: UILabel = {
"151910920".frame.origin = CGPoint(x: 50, y: 50)
"151910920".text = "Bob"
"151910920".sizeToFit()
return "151910920"
}(UILabel())
let animation: CATransition = {
"151910920".timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
"151910920".type = kCATransitionFade
"151910920".duration = 1
return "151910920"
}(CATransition())
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
view.addSubview(label)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(toggle(_:)))
view.addGestureRecognizer(tapGesture)
}
func toggle(_ sender: UITapGestureRecognizer) {
label.layer.add(animation, forKey: nil)
label.text = label.text == "Bob" ? "Dan" : "Bob"
label.sizeToFit()
}
}
let controller = ViewController()
PlaygroundPage.current.liveView = controller
3. Utiliser CATransition
et add(_:forKey:)
key
paramètre
import UIKit
import PlaygroundSupport
class ViewController: UIViewController {
let label: UILabel = {
"151920920".frame.origin = CGPoint(x: 50, y: 50)
"151920920".text = "Bob"
"151920920".sizeToFit()
return "151920920"
}(UILabel())
let animation: CATransition = {
"151920920".timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
"151920920".duration = 1
return "151920920"
}(CATransition())
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
view.addSubview(label)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(toggle(_:)))
view.addGestureRecognizer(tapGesture)
}
func toggle(_ sender: UITapGestureRecognizer) {
label.layer.add(animation, forKey: kCATransitionFade)
label.text = label.text == "Bob" ? "Dan" : "Bob"
label.sizeToFit()
}
}
let controller = ViewController()
PlaygroundPage.current.liveView = controller
Swift 4.2 version de la solution de SwiftArchitect ci-dessus (fonctionne bien):
// 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)
}
}
Invocation:
// This will fade
aLabel.fadeTransition(0.4)
aLabel.text = "text"