¿Cómo animar la propiedad textColor de un UILabel?


82

Por alguna razón, cuando intento animar textColor, no funcionará. El color del texto cambia repentinamente de A a B. ¿Es posible animarlo, de digamos rojo a negro?

Respuestas:


6

Esta respuesta es obsoleta y no es una buena solución para la pregunta original. La respuesta de @strange a continuación es mucho mejor y debe usarse en lugar de esta respuesta: https://stackoverflow.com/a/20892927/76559

// Antigua respuesta a continuación

La textColorpropiedad no está especificada como animable en los documentos, por lo que no creo que pueda hacerlo con un simple bloque de animaciones UIView ...

Esto probablemente podría hacerse de forma bastante tosca con un NSTimerdisparo cada par de milisegundos, cada vez estableciendo el color gradualmente de uno a otro.

Digo que esto es crudo porque requeriría una matriz o algún otro contenedor de valores de color preestablecidos que van desde el color de inicio hasta el color de finalización, y estoy seguro de que hay una manera de hacer esto usando animación central o algo así, simplemente no No sé lo que es.


o: una función que arroja una matriz con valores RGB entre A y B y un porcentaje dado. Sin embargo, no sé nada sobre algoritmos de color.
dontWatchMyProfile

aquí hay buenas soluciones: aquí y aquí gracias a Anna Karenina
chacal

4
Debería usar en CADisplayLinklugar de NSTimermanejar animaciones manualmente porque está sincronizado con las actualizaciones de pantalla. Consulte la sesión 236 de la WWDC 2014: Creación de interacciones interrumpibles y receptivas aproximadamente a las 13:00.
Douglas Hill

esta ya NO debería ser la respuesta aceptada, incluso si fuera cierta en ese momento. vea la respuesta de extraño a continuación
bitwit

Stack Overflow no me permitirá eliminar esta respuesta obsoleta, ya que ha sido aceptada. Mira la respuesta de @ strange a continuación.
Jasarien

194

En cambio, ¿ha intentado usar una transición de fundido cruzado en el objeto en sí de esta manera, le dará un efecto agradable de fundido de entrada y salida de un color a otro:

C objetivo

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

Rápido

UIView.transitionWithView(creditsLabel, duration: 0.25, options: .TransitionCrossDissolve, animations: {     
    self.creditsLabel.textColor = UIColor.redColor() 
}, 
completion: nil)

Esto es mejor que usar NSTimers, CATextLayers, etc., por varias razones. CATextLayer no tiene el soporte adecuado para el kerning de texto o NSAttributedText, y los NSTimers están retrasados ​​(además hay demasiado código). La animación de transición anterior hace el truco y también se puede usar en una animación en cadena. Tuve el mismo problema y ya probé las soluciones anteriores, pero este código simple funciona de maravilla.


7
Agradable, elegante, en realidad la mejor y más limpia solución.
maksa

17
Excelente. Funciona en Swift de la misma manera:UIView.transitionWithView(creditsLabel, duration: 0.3, options: .TransitionCrossDissolve, animations: { self.creditsLabel.textColor = UIColor.redColor() }, completion: nil)
SimplGy

8
solo una nota: esto solo funciona cuando la etiqueta es estática. Si hace esto y se modifica la posición de la etiqueta, la animación de desvanecimiento mostrará un artefacto feo.
Lukas Petr

No me funciona en Xcode 10.2.1 y Swift 5. El método 'shokaveli' a continuación sí lo hace
Martin

He estado buscando una forma de hacer esto en SwiftUI, pero no parece compatible en ese momento.
philipp

58

Solución Swift 4 :

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

Tenga en cuenta que esto solo funciona si tiene una instancia de UILabelpara la withpropiedad. Si haces algo como transition(with: outerView.label…)e intentas colocarlo dentro, fallará silenciosamente.
Sam Soffes

No funciona para mí por alguna razón. De repente, está haciendo el cambio en lugar de ser gradual durante la animación. :(
ScottyBlades

1
@ScottyBlades ¿tal vez estás haciendo la animación en el hilo de fondo? Intente envolver el código UIView.transition dentro de los corchetes DispatchQueue.main.async {}.
Budidino

1
FYI - La primera vez que lo intenté no funcionó y eso fue porque options: .easeInOutlo hice, así que lo cambié .transitionCrossDissolve y funcioné.
LeoGalante

13

La razón por la que textColor no es animable es que UILabel usa un CALayer regular en lugar de un CATextLayer.

Para hacer animable textColor (así como texto, fuente, etc.) podemos subclasificar UILabel para que use un CATextLayer.

Esto es bastante trabajo, pero afortunadamente ya lo hice :-)

Puede encontrar una explicación completa + un reemplazo de código abierto para UILabel en este artículo


9

Puede intentar crear otra instancia de UILabel o lo que sea que tenga el textColor, y luego aplicar la animación entre esas dos instancias (la con el antiguo textColor y la que tiene el nuevo textColor).


7

Esto fue lo ÚNICO que funcionó para mí:

let changeColor = CATransition()
changeColor.duration = 1

CATransaction.begin()

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

selected.nameLabel.textColor = .redColor()

CATransaction.commit()

6

Aquí está mi código para animar el color del texto de la etiqueta. La parte importante es establecer textColor en clearColor antes de la animación.

label.textColor = [UIColor clearColor];
[UIView transitionWithView:label duration:duration/4 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
    label.textColor = self.highlightedCellPrimaryTextColor;
} completion:^(BOOL finished) { }];

0

Me resultó bastante fácil colocar una UIView debajo de la etiqueta y animar su opacidad. La etiqueta debe agregarse a esa vista. Quizás no sea una buena solución desde el punto de vista del consumo de recursos, pero bastante sencilla.


0

actualizado swift 3.0

Acabo de cambiar los comentarios de @budidino

UIView.transition(with: my.label, duration: 0.3, options: .transitionCrossDissolve, animations: { my.label.textColor = .black }, completion: nil)

0

Gracias por la respuesta de @ Strange , funcionando perfectamente en Swift 5, Xcode 11 con un pequeño cambio de sintaxis. Estaba animando el color del texto para múltiples UILabels, si este también es tu caso, prueba esto

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)
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.