Sto impostando un nuovo valore di testo su a UILabel
. Attualmente, il nuovo testo appare bene. Tuttavia, vorrei aggiungere qualche animazione quando appare il nuovo testo. Mi chiedo cosa posso fare per animare l'aspetto del nuovo testo.
Sto impostando un nuovo valore di testo su a UILabel
. Attualmente, il nuovo testo appare bene. Tuttavia, vorrei aggiungere qualche animazione quando appare il nuovo testo. Mi chiedo cosa posso fare per animare l'aspetto del nuovo testo.
Risposte:
Mi chiedo se funziona e funziona perfettamente!
Objective-C
[UIView transitionWithView:self.label
duration:0.25f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
self.label.text = rand() % 2 ? @"Nice nice!" : @"Well done!";
} completion:nil];
Swift 3, 4, 5
UIView.transition(with: label,
duration: 0.25,
options: .transitionCrossDissolve,
animations: { [weak self] in
self?.label.text = (arc4random()() % 2 == 0) ? "One" : "Two"
}, completion: nil)
Per ottenere una vera transizione cross-dissolve (la vecchia etichetta sbiadisce mentre la nuova etichetta sbiadisce), non vuoi che la dissolvenza sia invisibile. Ciò comporterebbe uno sfarfallio indesiderato anche se il testo è invariato .
Utilizzare invece questo approccio:
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"
Vedi anche: Animare il testo UILabel tra due numeri?
Dimostrazione in iOS 10, 9, 8:
Testato con Xcode 8.2.1 e 7.1 , ObjectiveC su iOS 10 a 8.0 .
► Per scaricare l'intero progetto, cercare SO-3073520 in Ricette Swift .
-addAnimation:forKey
a tale etichetta, quindi si modifica il testo dell'etichetta.
Il modo corretto di sbiadire un UILabel (o qualsiasi UIView per quella materia) è usare un Core Animation Transition
. Questo non sfarfallerà, né si spegnerà in nero se il contenuto è invariato.
Una soluzione portatile e pulita consiste nell'utilizzare a Extension
in Swift (invocare prima di cambiare elementi visibili)
// 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)
}
}
L'invocazione è simile alla seguente:
// This will fade
aLabel.fadeTransition(0.4)
aLabel.text = "text"
► Trova questa soluzione su GitHub e ulteriori dettagli sulle ricette Swift .
MIT
licenza garantisce che il tuo Cocoapod può essere utilizzato liberamente da chiunque e da chiunque.
da iOS4 può ovviamente essere fatto con blocchi:
[UIView animateWithDuration:1.0
animations:^{
label.alpha = 0.0f;
label.text = newText;
label.alpha = 1.0f;
}];
Ecco il codice per farlo funzionare.
[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];
UILabel Extension Solution
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)
}
}
Funzione chiamata semplicemente da
uiLabel.textWithAnimation(text: "text you want to replace", duration: 0.2)
Grazie per tutti i consigli ragazzi. Spero che questo possa aiutare a lungo termine
Versione di Swift 4.2 della soluzione di SwiftArchitect sopra (funziona alla grande):
// 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)
}
}
Invocazione:
// This will fade
aLabel.fadeTransition(0.4)
aLabel.text = "text"
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"
})
O
UIView.animateWithDuration(0.2, animations: {
self.sampleLabel.alpha = 1
}, completion: {
(value: Bool) in
self.sampleLabel.alpha = 0.2
})
Con Swift 5, puoi scegliere uno dei due seguenti esempi di codice Playground per animare le UILabel
modifiche al testo con alcune animazioni incrociate.
UIView
il transition(with:duration:options:animations:completion:)
metodo di classeimport 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
e CALayer
's add(_:forKey:)
il metodoimport 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
Soluzione Swift 4.2 (prendendo la risposta 4.0 e l'aggiornamento per la compilazione di nuovi enum)
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"
}
I valori predefiniti di sistema di 0,25 per duration
e .curveEaseInEaseOut per timingFunction
sono spesso preferibili per la coerenza tra le animazioni e possono essere omessi:
let animation = CATransition()
label.layer.add(animation, forKey: nil)
label.text = "New text"
che è lo stesso di scrivere questo:
let animation = CATransition()
animation.duration = 0.25
animation.timingFunction = .curveEaseInEaseOut
label.layer.add(animation, forKey: nil)
label.text = "New text"
Questo è un metodo di estensione C # UIView basato sul codice di @ SwiftArchitect. Quando è coinvolto il layout automatico e i controlli devono spostarsi a seconda del testo dell'etichetta, questo codice chiamante utilizza la supervisione dell'etichetta come vista di transizione anziché l'etichetta stessa. Ho aggiunto un'espressione lambda per l'azione per renderla più incapsulata.
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();
}
Prefisso telefonico:
labelSuperview.FadeTransition( 0.5d, () =>
{
if ( condition )
label.Text = "Value 1";
else
label.Text = "Value 2";
} );
Se vuoi farlo Swift
con un ritardo, prova questo:
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
})
}
})
}
utilizzando la seguente funzione creata da @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)
}
che diventerà questo in Swift 3
func delay(_ delay:Double, closure:()->()) {
let when = DispatchTime.now() + delay
DispatchQueue.main.after(when: when, execute: closure)
}
C'è un'altra soluzione per raggiungere questo obiettivo. È stato descritto qui . L'idea è la sottoclasse UILabel
e l'override della action(for:forKey:)
funzione nel modo seguente:
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)
}
}
Esempi di utilizzo:
// 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!"