Animar el cambio de texto en UILabel


Estoy estableciendo un nuevo valor de texto a UILabel. Actualmente, el nuevo texto aparece muy bien. Sin embargo, me gustaría añadir alguna animación cuando aparezca el nuevo texto. Me pregunto qué puedo hacer para animar la aparición del nuevo texto.

Author: IPS Brar, 2010-06-19

10 answers

Objetivo-C

Para lograr una transición verdadera de disolución cruzada (la etiqueta antigua se desvanece mientras que la nueva etiqueta se desvanece), no desea desvanecerse a invisible. Daría lugar a parpadeo no deseado incluso si el texto no cambia.

Utilice este enfoque en su lugar:

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"

Véase también: ¿Animar texto UILabel entre dos números?

Demostración en iOS 10, 9, 8:

En blanco, luego transición de fundido de 1 a 5


Probado con Xcode 8.2.1 & 7.1, ObjectiveC en iOS 10 a 8.0.

► Para descargar el proyecto completo, busque SO-3073520 en Swift Recipes .

 147
Author: SwiftArchitect,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:31

Me pregunto si funciona y funciona perfectamente!

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

UIView.transition(with: label,
              duration: 0.25,
               options: .transitionCrossDissolve,
            animations: { [weak self] in
                self?.label.text = (arc4random()() % 2 == 0) ? "One" : "Two"
         }, completion: nil)
 141
Author: Anton Gaenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-16 10:03:25

Swift 4

La forma correcta de desvanecer un UILabel (o cualquier UIView para el caso) es usar un Core Animation Transition. Esto no parpadeo, ni fundido a negro si el contenido es invariable.

Una solución portátil y limpia es usar un Extension en Swift (invocar elementos visibles cambiantes anteriores)

// 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)
    }
}

La invocación se ve así:

// This will fade
aLabel.fadeTransition(0.4)
aLabel.text = "text"

En blanco, luego transición de fundido de 1 a 5


► Encuentre esta solución en GitHub y detalles adicionales en Swift Recetas.

 81
Author: SwiftArchitect,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-27 17:16:06

Desde iOS4 se puede hacer obviamente con bloques:

[UIView animateWithDuration:1.0
                 animations:^{
                     label.alpha = 0.0f;
                     label.text = newText;
                     label.alpha = 1.0f;
                 }];
 21
Author: Mapedd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-28 19:36:14

Aquí está el código para hacer que esto funcione.

[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];
 17
Author: Joo Park,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-18 23:28:57

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
})
 3
Author: A.G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-11 09:05:19

Este es un método de extensión C# UIView que se basa en el código de @SwiftArchitect. Cuando el diseño automático está involucrado y los controles necesitan moverse dependiendo del texto de la etiqueta, este código de llamada utiliza la Supervisión de la etiqueta como la vista de transición en lugar de la etiqueta misma. Agregué una expresión lambda para la acción para hacerla más encapsulada.

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();
}

Código de llamada:

  labelSuperview.FadeTransition( 0.5d, () =>
  {
    if ( condition )
      label.Text = "Value 1";
    else
      label.Text = "Value 2";
  } );
 1
Author: Gary Z,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-09 04:58:56

Si quieres hacer esto en Swift con un retraso, prueba esto:

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

                    })
                }

        })
    }

Usando la siguiente función creada por @ 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)
}

Que se convertirá en esto en Swift 3

func delay(_ delay:Double, closure:()->()) {
    let when = DispatchTime.now() + delay
    DispatchQueue.main.after(when: when, execute: closure)
}
 0
Author: ColossalChris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:59

De acuerdo con sus gustos y necesidades, puede elegir uno de los tres fragmentos de código siguientes para animar los cambios de texto de su UILabel con alguna animación de disolución cruzada:

1. Usando transition(with:duration:options:animations:completion:)

import UIKit
import PlaygroundSupport

class ViewController: UIViewController {

    let label: UILabel = {
        $0.frame.origin = CGPoint(x: 50, y: 50)
        $0.text = "Bob"
        $0.sizeToFit()
        return $0
    }(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. Usando CATransition y CATransition's type propiedad

import UIKit
import PlaygroundSupport

class ViewController: UIViewController {

    let label: UILabel = {
        $0.frame.origin = CGPoint(x: 50, y: 50)
        $0.text = "Bob"
        $0.sizeToFit()
        return $0
    }(UILabel())
    let animation: CATransition = {
        $0.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        $0.type = kCATransitionFade
        $0.duration = 1
        return $0
    }(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. Usando CATransition y add(_:forKey:) key parámetro

import UIKit
import PlaygroundSupport

class ViewController: UIViewController {

    let label: UILabel = {
        $0.frame.origin = CGPoint(x: 50, y: 50)
        $0.text = "Bob"
        $0.sizeToFit()
        return $0
    }(UILabel())
    let animation: CATransition = {
        $0.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        $0.duration = 1
        return $0
    }(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
 0
Author: Imanou Petit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-21 12:50:30

Swift 4.2 versión de la solución de SwiftArchitect anterior (funciona muy 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)
        }
    }

Invocación:

    // This will fade

aLabel.fadeTransition(0.4)
aLabel.text = "text"
 0
Author: winnie-ru,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-26 10:50:27