El sistema de animación de propiedades es un framework sólido que te permite para animar casi cualquier cosa. Puedes definir una animación para cambiar las propiedades de cualquier objeto en el tiempo. independientemente de si se dibuja en la pantalla o no. Una animación de propiedades cambia la configuración (un campo de un objeto) durante un período especificado. Para animar algo, debes especificar del objeto que deseas animar, como la posición de un objeto en la pantalla, quieres animarla y entre qué valores quieres animarla.
El sistema de animación de propiedades te permite definir las siguientes características de un animación:
- Duración: Puedes especificar la duración de una animación. El valor predeterminado es 300 ms.
- Interpolación de tiempo: Puedes especificar cómo se calculan los valores para la propiedad como una función del tiempo transcurrido actual de la animación.
- Cantidad de repeticiones y comportamiento: Puedes especificar si se debe repetir o no una animación cuando se ejecute. alcanza el final de una duración y cuántas veces repetir la animación. También puedes especifica si quieres que la animación se reproduzca en orden inverso. Configurando reproducción inversa la animación avanza y luego retrocede repetidamente, hasta alcanzar el número de repeticiones.
- Conjuntos de animadores: Puedes agrupar animaciones en conjuntos lógicos que se reproducen juntos o de forma secuencial o con retrasos especificados.
- Retraso de la actualización de fotogramas: Puedes especificar la frecuencia con la que se actualizan los fotogramas de la animación. El predeterminada está configurada para actualizarse cada 10 ms, pero la velocidad a la que tu aplicación puede actualizar los fotogramas depende de qué tan ocupado esté el sistema en general y de qué tan rápido este pueda atender el temporizador subyacente.
Para ver un ejemplo completo de la animación de propiedades, consulta la
Clase ChangeColor
en CustomTransition
en GitHub.
Cómo funciona la animación de propiedades
Primero, usemos un ejemplo sencillo para ver cómo funciona una animación. En la figura 1, se muestra un
objeto hipotético animado con su propiedad x
, que representa su
ubicación horizontal en una pantalla. La duración de la animación se establece en 40 ms y la distancia
para viajar es de 40 píxeles. Cada 10 ms, que es la frecuencia de actualización de fotogramas predeterminada, el objeto se mueve
horizontalmente en 10 píxeles. Al final de los 40 ms, la animación se detiene y el objeto termina en
posición horizontal 40. Este es un ejemplo de animación con interpolación lineal, es decir, que
se mueve a una velocidad constante.
También puedes especificar que las animaciones tengan una interpolación no lineal. En la figura 2, se ilustra un objeto hipotético que se acelera al comienzo de la animación y se desacelera al final de la animación. El objeto recorre los 40 píxeles en 40 ms, pero de forma no lineal. En la al principio, esta animación acelera hasta la mitad y luego se desacelera desde la punto medio hasta el final de la animación. Como se muestra en la figura 2, la distancia recorrida al principio y al final de la animación es menor que la mitad.
Analicemos en detalle cómo los componentes importantes del sistema de animación de propiedades calcularía animaciones como las ilustradas más arriba. En la figura 3, se muestra cómo las clases principales trabajan entre sí.
El objeto ValueAnimator
realiza un seguimiento del tiempo de la animación.
como el tiempo de ejecución de la animación y el valor actual de la propiedad
animaciones.
El ValueAnimator
encapsula un TimeInterpolator
, que define la interpolación de la animación, y un TypeEvaluator
, que define cómo calcular valores para la propiedad que se va a procesar.
animada. Por ejemplo, en la Figura 2, el TimeInterpolator
que se usaría sería
AccelerateDecelerateInterpolator
y TypeEvaluator
serían IntEvaluator
.
Para iniciar una animación, crea un elemento ValueAnimator
y asígnale la
valores de inicio y finalización para la propiedad que deseas animar, junto con la duración de
la animación. Cuando llamas a start()
, la animación
antes de comenzar a usar el servicio. Durante toda la animación, ValueAnimator
calcula una fracción transcurrida.
entre 0 y 1, según la duración de la animación y el tiempo transcurrido. El
la fracción transcurrida representa el porcentaje de tiempo que se completó la animación, es decir, 0 significa 0%
y 1 significa 100%. Por ejemplo, en la Figura 1, la fracción transcurrida en t = 10 ms sería 0 .25
porque la duración total es t = 40 ms.
Cuando ValueAnimator
termina de calcular una fracción transcurrida,
llama al TimeInterpolator
que está establecido actualmente para calcular un
fracción interpolada. Una fracción interpolada mapea la fracción transcurrida a una nueva
que tiene en cuenta la interpolación de tiempo establecida. Por ejemplo, en la Figura 2,
debido a que la animación se acelera lentamente, la fracción interpolada, aproximadamente 0 .15, es menor que la
fracción transcurrida, 0.25, en t = 10 ms. En la Figura 1, la fracción interpolada es siempre la misma que
la fracción transcurrida.
Cuando se calcula la fracción interpolada, ValueAnimator
llama
el TypeEvaluator
adecuado para calcular el valor
propiedad que estás animando, según la fracción interpolada, el valor inicial y el
el valor final de la animación. Por ejemplo, en la Figura 2, la fracción interpolada fue 0 .15 en t =
10 ms. Por lo tanto, el valor de la propiedad en ese momento sería 0.15 × (40 - 0), o bien 6.
Diferencias entre la animación de propiedades y la animación de vista
El sistema de animación de vista proporciona la capacidad de solo animar View
.
objetos, así que si quieres animar objetos que no sean View
, debes implementar
tu propio código para hacerlo. El sistema de animación de vistas
también se ve limitado por el hecho de que
expone algunos aspectos de un objeto View
para animar, como el escalamiento y
rotación de un objeto View, pero no el color de fondo, por ejemplo.
Otra desventaja del sistema de animación de vista es que solo modifica se dibujó la vista, no la vista en sí. Por ejemplo, si animaste un botón para que se mueva en la pantalla, el botón se muestra correctamente, pero la ubicación real donde puedes hacer clic no cambia, por lo que debes implementar tu propia lógica para controlar esto.
Con el sistema de animación de propiedades, estas restricciones se quitan por completo y puedes animar cualquier propiedad de cualquier objeto (elementos View o no), y el objeto en sí se modifica. El sistema de animación de propiedades también es más robusto en la forma en que lleva a cabo la animación. En en un nivel alto, debes asignar animadores a las propiedades que quieres animar, como el color, la posición o el tamaño y puede definir aspectos de la animación, como la interpolación y y la sincronización de varios animadores.
Sin embargo, el sistema de animación de vista se configura en menos tiempo y no requiere tanto código. Si la animación de vista logra todo lo que necesitas hacer o si tu código funciona como quieres, no es necesario usar el sistema de animación de propiedades. También podría tiene sentido usar ambos sistemas de animación para diferentes situaciones si surge el caso de uso.
Descripción general de la API
Puedes encontrar la mayoría de las API del sistema de animación de propiedades en android.animation
. Como el sistema de animación de vistas
define muchos interpoladores en android.view.animation
, puedes usar
en el sistema de animación de propiedades. En las siguientes tablas, se describen los principales
del sistema de animación de propiedades.
La clase Animator
proporciona la estructura básica para crear
animaciones. Por lo general, no se usa esta clase directamente, ya que solo proporciona una
que debe extenderse para admitir por completo la animación de valores. Lo siguiente
las subclases extienden Animator
:
Clase | Descripción |
---|---|
ValueAnimator |
El motor principal de sincronización para la animación de propiedades que también calcula los valores de la
propiedad de animación. Tiene toda la funcionalidad principal que calcula la animación
y contiene los detalles de sincronización de cada animación, información sobre si un
repeticiones de animación, objetos de escucha que reciben eventos de actualización y la capacidad de establecer
tipos de datos que se evaluarán. La animación tiene dos partes: calcular la animación
valores y configurarlos en el objeto y la propiedad que se van a animar. ValueAnimator no lleva a cabo la segunda pieza, por lo que debes escucharla.
para las actualizaciones de los valores calculados por ValueAnimator y
y modificar los objetos que quieres animar con tu propia lógica. Consulta la sección sobre
Animación con ValueAnimator para obtener más información. |
ObjectAnimator |
Una subclase de ValueAnimator que te permite establecer un objetivo
las propiedades de objeto y objeto para animar. Esta clase actualiza la propiedad según corresponda cuando
calcula un nuevo valor para la animación. Deseas usar
ObjectAnimator la mayor parte del tiempo,
porque facilita mucho el proceso de animar valores en los objetos de destino. Sin embargo,
A veces, quieres usar ValueAnimator directamente porque ObjectAnimator tiene algunas restricciones más, como requerir requisitos de uso
de acceso que estén presentes en el objeto de destino. |
AnimatorSet |
Proporciona un mecanismo para agrupar animaciones de manera que se ejecuten en relación entre sí. Puedes configurar animaciones para que se reproduzcan juntas, un retraso específico. Consulta la sección Coorografía de varios elementos animaciones con Conjuntos de animaciones para obtener más información. |
Los evaluadores le indican al sistema de animación de propiedades cómo calcular valores para un determinado
propiedad. Toma los datos de tiempo que proporciona un Animator
.
el valor de inicio y fin de la animación, y calcular los valores animados de la propiedad
con base en estos datos. El sistema de animación de propiedades proporciona los siguientes evaluadores:
Clase/interfaz | Descripción |
---|---|
IntEvaluator |
Es el evaluador predeterminado para calcular valores de las propiedades int . |
FloatEvaluator |
Es el evaluador predeterminado para calcular valores de las propiedades float . |
ArgbEvaluator |
El evaluador predeterminado para calcular valores de las propiedades de color que se representan como valores hexadecimales. |
TypeEvaluator |
Es una interfaz que te permite crear tu propio evaluador. Si estás animando un
del objeto que no es int , float ni color,
debes implementar la interfaz TypeEvaluator para especificar cómo
para calcular los valores animados de la propiedad del objeto. También puedes especificar un TypeEvaluator personalizado para int , float y un color.
valores, si quieres procesar esos tipos de forma diferente al comportamiento predeterminado.
Para obtener más información, consulta la sección Cómo usar un TypeEvaluator.
información para escribir un evaluador personalizado. |
Un interpolador de tiempo define cómo se calculan los valores específicos en una animación como una
función del tiempo. Por ejemplo, puedes especificar que las animaciones se produzcan de forma lineal en todo el
animación, lo que significa que se mueve de manera uniforme todo el tiempo, o puedes especificar animaciones
para usar tiempo no lineal, por ejemplo, acelerar al inicio y desacelerar al
final de la animación. En la tabla 3, se describen los interpoladores que contiene android.view.animation
. Si ninguno de los interpoladores proporcionados se ajusta
según tus necesidades, implementa la interfaz TimeInterpolator
y crea una propia. Consulta Usa interpoladores para obtener más información sobre cómo escribir un diseño personalizado.
interpolador.
Clase/interfaz | Descripción |
---|---|
AccelerateDecelerateInterpolator |
Es un interpolador cuya velocidad de cambio comienza y finaliza lentamente, pero se acelera. por el medio. |
AccelerateInterpolator |
Es un interpolador cuya velocidad de cambio comienza lentamente y, luego, acelera. |
AnticipateInterpolator |
Es un interpolador cuyo cambio comienza hacia atrás y luego se desplaza hacia delante. |
AnticipateOvershootInterpolator |
Es un interpolador cuyo cambio comienza hacia atrás, se lanza hacia delante y se sobrepasa. el valor objetivo y, finalmente, regresa al valor final. |
BounceInterpolator |
Es un interpolador cuyo cambio rebota en el final. |
CycleInterpolator |
Es un interpolador cuya animación se repite durante un número específico de ciclos. |
DecelerateInterpolator |
Es un interpolador cuya tasa de cambio comienza rápidamente y luego se desacelera. |
LinearInterpolator |
Es un interpolador cuya velocidad de cambio es constante. |
OvershootInterpolator |
Es un interpolador cuyo cambio se lanza hacia adelante y supera el último valor que luego regresa. |
TimeInterpolator |
Es una interfaz que te permite implementar tu propio interpolador. |
Cómo animar valores con ValueAnimator
La clase ValueAnimator
te permite animar valores de algún tipo para el
la duración de una animación mediante la especificación de un conjunto de int
, float
o color
valores para animar. Puedes obtener un ValueAnimator
llamando a uno de
sus métodos de fábrica: ofInt()
, ofFloat()
o ofObject()
Por ejemplo:
Kotlin
ValueAnimator.ofFloat(0f, 100f).apply { duration = 1000 start() }
Java
ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f); animation.setDuration(1000); animation.start();
En este código, ValueAnimator
comienza a calcular los valores de la
animación, entre 0 y 100, por una duración de 1,000 ms, cuando se ejecuta el método start()
.
También puedes especificar un tipo personalizado para animarlo de la siguiente manera:
Kotlin
ValueAnimator.ofObject(MyTypeEvaluator(), startPropertyValue, endPropertyValue).apply { duration = 1000 start() }
Java
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue); animation.setDuration(1000); animation.start();
En este código, ValueAnimator
comienza a calcular los valores de la
entre startPropertyValue
y endPropertyValue
con el comando
lógica proporcionada por MyTypeEvaluator
durante 1,000 ms, cuando se ejecuta el método start()
.
Para usar los valores de la animación, agrega un elemento
AnimatorUpdateListener
al objeto ValueAnimator
, como se muestra en
siguiente código:
Kotlin
ValueAnimator.ofObject(...).apply { ... addUpdateListener { updatedAnimation -> // You can use the animated value in a property that uses the // same type as the animation. In this case, you can use the // float value in the translationX property. textView.translationX = updatedAnimation.animatedValue as Float } ... }
Java
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator updatedAnimation) { // You can use the animated value in a property that uses the // same type as the animation. In this case, you can use the // float value in the translationX property. float animatedValue = (float)updatedAnimation.getAnimatedValue(); textView.setTranslationX(animatedValue); } });
En onAnimationUpdate()
puedes acceder al valor actualizado de la animación y usarlo en una propiedad de
una de tus vistas. Para obtener más información sobre los objetos de escucha, consulta la sección sobre
Objetos de escucha de la animación.
Cómo animar propiedades con ObjectAnimator
ObjectAnimator
es una subclase de ValueAnimator
(que se analizó en la sección anterior) y combina la sincronización.
y el cálculo del valor de ValueAnimator
con la capacidad de
animar una propiedad con nombre de un objeto de destino. Esto hace que animar cualquier objeto sea mucho más fácil, ya que
ya no necesitas implementar ValueAnimator.AnimatorUpdateListener
,
porque la propiedad animada se actualiza automáticamente.
Crear una instancia de ObjectAnimator
es similar a una ValueAnimator
, pero también debes especificar el objeto y el nombre de su propiedad (como
(una cadena) junto con los valores entre los que se debe animar:
Kotlin
ObjectAnimator.ofFloat(textView, "translationX", 100f).apply { duration = 1000 start() }
Java
ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f); animation.setDuration(1000); animation.start();
Para actualizar las propiedades de ObjectAnimator
correctamente, debes hacer lo siguiente:
- La propiedad del objeto que estás animando debe tener una función set (en mayúsculas y minúsculas) con el formato de
set<PropertyName>()
Debido a queObjectAnimator
actualiza automáticamente la propiedad durante la animación, debe poder acceder a ella. con este método set. Por ejemplo, si el nombre de la propiedad esfoo
, debes tener un métodosetFoo()
Si este método set no existe, tendrás tres Opciones:- Agrega el método establecedor a la clase si tienes los derechos para hacerlo.
- Use una clase wrapper que tenga derechos para cambiar y haga que ese wrapper reciba el valor con un método set válido y lo reenvía al objeto original.
- Usa
ValueAnimator
en su lugar.
- Si especificas solo un valor para el parámetro
values...
en uno de los métodos de fábricaObjectAnimator
, se supone que es el valor final de la animación. Por lo tanto, la propiedad del objeto que estás animando debe tener una función de método get. que se usa para obtener el valor de inicio de la animación. La función de método get debe estar formato deget<PropertyName>()
. Por ejemplo, si el nombre de la propiedad esfoo
, debes tener un métodogetFoo()
. - Los métodos get (si es necesario) y set de la propiedad que estás animando deben
operar en el mismo tipo que los valores de inicio y finalización que especifiques en
ObjectAnimator
Por ejemplo, debes tenertargetObject.setPropName(float)
ytargetObject.getPropName()
si construyes el siguienteObjectAnimator
:ObjectAnimator.ofFloat(targetObject, "propName", 1f)
- Según la propiedad o el objeto que estés animando, es posible que debas llamar al método
invalidate()
en una vista para forzar a la pantalla a volver a dibujarse con el valores animados actualizados. Puedes hacerlo en laonAnimationUpdate()
devolución de llamada. Por ejemplo, animar la propiedad de color de un objeto Drawable solo genera actualizaciones en el la pantalla cuando ese objeto se vuelva a dibujar a sí mismo. Todos los establecedores de propiedades en la vista, comosetAlpha()
ysetTranslationX()
invalidar la vista correctamente, por lo que no es necesario que invalides la vista cuando las llames métodos con valores nuevos. Para obtener más información sobre los objetos de escucha, consulta la sección sobre Objetos de escucha de la animación.
Cómo coreografiar varias animaciones con un AnimatorSet
En muchos casos, querrás reproducir una animación que dependa del inicio de otra animación o
para finalizar la tarea. El sistema Android te permite agrupar animaciones en una AnimatorSet
para que puedas especificar si deseas iniciar animaciones.
de forma simultánea, secuencial o después de un retraso especificado. También puedes anidar objetos AnimatorSet
entre sí.
El siguiente fragmento de código reproduce el siguiente Animator
los objetos de la siguiente manera:
- Reproduce
bounceAnim
. - Reproduce
squashAnim1
,squashAnim2
,stretchAnim1
ystretchAnim2
al mismo tiempo. - Reproduce
bounceBackAnim
. - Reproduce
fadeAnim
.
Kotlin
val bouncer = AnimatorSet().apply { play(bounceAnim).before(squashAnim1) play(squashAnim1).with(squashAnim2) play(squashAnim1).with(stretchAnim1) play(squashAnim1).with(stretchAnim2) play(bounceBackAnim).after(stretchAnim2) } val fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply { duration = 250 } AnimatorSet().apply { play(bouncer).before(fadeAnim) start() }
Java
AnimatorSet bouncer = new AnimatorSet(); bouncer.play(bounceAnim).before(squashAnim1); bouncer.play(squashAnim1).with(squashAnim2); bouncer.play(squashAnim1).with(stretchAnim1); bouncer.play(squashAnim1).with(stretchAnim2); bouncer.play(bounceBackAnim).after(stretchAnim2); ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(bouncer).before(fadeAnim); animatorSet.start();
Objetos de escucha de la animación
Puedes escuchar eventos importantes durante la duración de una animación con los objetos de escucha que se describen a continuación.
Animator.AnimatorListener
onAnimationStart()
- Se lo llama cuando comienza la animación.onAnimationEnd()
: Se llama cuando finaliza la animación.onAnimationRepeat()
: Se lo llama cuando la animación se repite.onAnimationCancel()
: Se lo llama cuando se cancela la animación. Una animación cancelada También llama aonAnimationEnd()
, independientemente de cómo se hayan finalizado.
ValueAnimator.AnimatorUpdateListener
-
onAnimationUpdate()
: Se lo llama en todos los fotogramas de la animación. Escuchar este evento para usar los valores calculados que generóValueAnimator
durante un animación. Para usar el valor, consulta el objetoValueAnimator
Se pasa al evento para obtener el valor animado actual con el métodogetAnimatedValue()
. Implementar esto se requiere el objeto de escucha si usasValueAnimator
.Según la propiedad o el objeto que estés animando, quizás debas llamar
invalidate()
en una vista para forzar esa área de la para volver a dibujarse con los nuevos valores animados. Por ejemplo, animar el color de un objeto de elemento de diseño solo causa actualizaciones en la pantalla cuando ese objeto se vuelve a dibujar. Todos los establecedores de propiedades en View, comosetAlpha()
ysetTranslationX()
invalida la vista de forma correcta, por lo que no necesitas invalidar la vista cuando llames a estos métodos con valores nuevos.
-
Puedes extender la clase AnimatorListenerAdapter
en lugar de
implementando la interfaz Animator.AnimatorListener
, si no
implementar todos los métodos de Animator.AnimatorListener
interfaz de usuario. La clase AnimatorListenerAdapter
proporciona variables de
de los métodos que puedes anular.
Por ejemplo, el siguiente fragmento de código crea un AnimatorListenerAdapter
por solo onAnimationEnd()
devolución de llamada:
Kotlin
ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply { duration = 250 addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { balls.remove((animation as ObjectAnimator).target) } }) }
Java
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); fadeAnim.addListener(new AnimatorListenerAdapter() { public void onAnimationEnd(Animator animation) { balls.remove(((ObjectAnimator)animation).getTarget()); }
Cómo animar cambios de diseño en objetos ViewGroup
El sistema de animación de propiedades permite animar cambios en objetos ViewGroup y ofrece una manera fácil de animar objetos View.
Puedes animar los cambios de diseño en un objeto ViewGroup con el
Clase LayoutTransition
. Las vistas dentro de un ViewGroup pueden
pasan una animación que aparece y desaparece cuando las agregas
quitarlos de un ViewGroup o cuando llames al
Método setVisibility()
con
VISIBLE
, INVISIBLE
o
GONE
Las vistas restantes en ViewGroup también pueden
animar en sus nuevas posiciones cuando agregues o quites Views. Puedes definir
las siguientes animaciones en un objeto LayoutTransition
llamando a setAnimator()
y pasar un objeto Animator
con uno de los
Las siguientes constantes LayoutTransition
:
APPEARING
: Es una marca que indica la animación que se ejecuta en elementos que se que aparezcan en el contenedor.CHANGE_APPEARING
: Es una marca que indica la animación que se ejecuta en elementos que se cambian debido a que aparece un nuevo elemento en el contenedor.DISAPPEARING
: Es una marca que indica la animación que se ejecuta en elementos que se del contenedor.CHANGE_DISAPPEARING
: Es una marca que indica la animación que se ejecuta en elementos que cambian debido a la desaparición de un elemento del contenedor.
Puedes definir tus propias animaciones personalizadas para estos cuatro tipos de eventos y, así, personalizar el aspecto. de tus transiciones de diseño o simplemente decirle al sistema de animación que use las animaciones predeterminadas.
Para establecer el atributo android:animateLayoutchanges
en true
para el elemento
ViewGroup haz lo siguiente:
<LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="match_parent" android:id="@+id/verticalContainer" android:animateLayoutChanges="true" />
Si estableces este atributo como verdadero, se animarán automáticamente las vistas que se agreguen o quiten de la ViewGroup, así como las vistas restantes en ViewGroup.
Cómo animar los cambios de estado de las vistas con StateListAnimator
La clase StateListAnimator
te permite definir los animadores que se ejecutan cuando
cambia el estado de una vista. Este objeto se comporta como wrapper de un
Animator
, llamando a esa animación cada vez que se especifica
cambia el estado de vista (como "presionada" o "enfocada").
El StateListAnimator
se puede definir en un recurso XML con una raíz.
Elemento <selector>
y elementos <item>
secundarios que especifican cada uno
un estado de vista diferente definido por la clase StateListAnimator
. Cada
<item>
contiene la definición de un conjunto de animación de propiedades.
Por ejemplo, el siguiente archivo crea un animador de listas de estados que cambia la escala x e y de la vista cuando se la presiona:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- the pressed state; increase x and y size to 150% --> <item android:state_pressed="true"> <set> <objectAnimator android:propertyName="scaleX" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1.5" android:valueType="floatType"/> <objectAnimator android:propertyName="scaleY" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1.5" android:valueType="floatType"/> </set> </item> <!-- the default, non-pressed state; set x and y size to 100% --> <item android:state_pressed="false"> <set> <objectAnimator android:propertyName="scaleX" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1" android:valueType="floatType"/> <objectAnimator android:propertyName="scaleY" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1" android:valueType="floatType"/> </set> </item> </selector>
Para adjuntar el animador de listas de estados a una vista, agrega el elemento
android:stateListAnimator
de la siguiente manera:
<Button android:stateListAnimator="@xml/animate_scale" ... />
Ahora, se usan las animaciones definidas en animate_scale.xml
cuando el botón
cambios de estado.
Como alternativa, si deseas asignar un animador de listas de estados a una vista de tu código, usa el
AnimatorInflater.loadStateListAnimator()
y asigna el animador a
tu vista con el método View.setStateListAnimator()
.
En lugar de animar propiedades de la vista, puedes reproducir una animación de elementos de diseño entre
cambios de estado con AnimatedStateListDrawable
.
Algunos de los widgets del sistema en
Android 5.0 usa estas animaciones de forma predeterminada. En el siguiente ejemplo, se muestra cómo
para definir un AnimatedStateListDrawable
como un recurso XML:
<!-- res/drawable/myanimstatedrawable.xml --> <animated-selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- provide a different drawable for each state--> <item android:id="@+id/pressed" android:drawable="@drawable/drawableP" android:state_pressed="true"/> <item android:id="@+id/focused" android:drawable="@drawable/drawableF" android:state_focused="true"/> <item android:id="@id/default" android:drawable="@drawable/drawableD"/> <!-- specify a transition --> <transition android:fromId="@+id/default" android:toId="@+id/pressed"> <animation-list> <item android:duration="15" android:drawable="@drawable/dt1"/> <item android:duration="15" android:drawable="@drawable/dt2"/> ... </animation-list> </transition> ... </animated-selector>
Cómo usar un TypeEvaluator
Si deseas animar un tipo desconocido para el sistema Android, puedes crear uno propio
evaluador implementando la interfaz TypeEvaluator
. Los tipos que
conocidos por el sistema Android son int
, float
o un color, que son
compatible con los tipos IntEvaluator
, FloatEvaluator
y ArgbEvaluator
y evaluadores.
Solo hay un método para implementar en TypeEvaluator
interfaz, el método evaluate()
. Esto permite
el animador que estás usando para devolver un valor apropiado para tu propiedad animada en el
punto actual de la animación. La clase FloatEvaluator
demuestra
cómo hacerlo:
Kotlin
private class FloatEvaluator : TypeEvaluator<Any> { override fun evaluate(fraction: Float, startValue: Any, endValue: Any): Any { return (startValue as Number).toFloat().let { startFloat -> startFloat + fraction * ((endValue as Number).toFloat() - startFloat) } } }
Java
public class FloatEvaluator implements TypeEvaluator { public Object evaluate(float fraction, Object startValue, Object endValue) { float startFloat = ((Number) startValue).floatValue(); return startFloat + fraction * (((Number) endValue).floatValue() - startFloat); } }
Nota: Cuando se ejecuta ValueAnimator
(o ObjectAnimator
), se calcula una fracción transcurrida actual del
animación (un valor entre 0 y 1) y luego calcula una versión interpolada de esa
según el interpolador que estés usando. La fracción interpolada es lo que recibe tu TypeEvaluator
a través del parámetro fraction
, por lo que debes hacer lo siguiente:
no tendrá que tener en cuenta el interpolador al calcular los valores animados.
Cómo usar interpoladores
Un interpolador define cómo se calculan los valores específicos en una animación como una función de tiempo. Por ejemplo, puedes especificar que las animaciones se produzcan linealmente en toda la animación lo que significa que la animación se mueve de manera uniforme todo el tiempo, o puedes especificar las animaciones tiempo no lineal, por ejemplo, usando la aceleración o desaceleración al principio o al final de animación.
Los interpoladores del sistema de animación reciben una fracción de los animadores que representan la
tiempo transcurrido de la animación. Los interpoladores modifican esta fracción para que coincida con el tipo de
la animación que pretende proporcionar. El sistema Android proporciona un conjunto de interpoladores comunes en
android.view.animation package
Si ninguno de estos es adecuado para
de servicio, puedes implementar la interfaz TimeInterpolator
y crear tu
por sí solas.
A continuación, se muestra un ejemplo comparativo de cómo el interpolador predeterminado AccelerateDecelerateInterpolator
y el LinearInterpolator
calculan las fracciones interpoladas.
LinearInterpolator
no tiene efecto en la fracción transcurrida. AccelerateDecelerateInterpolator
acelera en la animación y
se desacelera. Los siguientes métodos definen la lógica para estos interpoladores:
AccelerateDecelerateInterpolator
Kotlin
override fun getInterpolation(input: Float): Float = (Math.cos((input + 1) * Math.PI) / 2.0f).toFloat() + 0.5f
Java
@Override public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; }
LinearInterpolator
Kotlin
override fun getInterpolation(input: Float): Float = input
Java
@Override public float getInterpolation(float input) { return input; }
La siguiente tabla representa los valores aproximados que calculan estas interpoladores para una animación que dura 1000 ms:
ms transcurridos | Fracción transcurrida/fracción interpolada (lineal) | Fracción interpolada (aceleración/desaceleración) |
---|---|---|
0 | 0 | 0 |
200 | 0.2 | 0.1 |
400 | 0.4 | 0.345 |
600 | 0.6 | 0.8 |
800 | 0.8 | 0.9 |
1000 | 1 | 1 |
Como se muestra en la tabla, LinearInterpolator
cambia los valores.
a la misma velocidad, 0.2 por cada 200 ms que transcurren. El AccelerateDecelerateInterpolator
cambia los valores más rápido que LinearInterpolator
entre 200 ms y 600 ms, y más lento entre 600 ms y
1,000 ms.
Cómo especificar fotogramas clave
Un objeto Keyframe
consta de un par de tiempo/valor que te permite definir
un estado específico en un momento específico de una animación. Cada fotograma también puede tener su propio
interpolador para controlar el comportamiento de la animación en el intervalo entre los resultados
y la hora de este fotograma clave.
Para crear una instancia de un objeto Keyframe
, debes usar una de las instancias
ofInt()
, ofFloat()
o ofObject()
para obtener el tipo adecuado de Keyframe
. Luego, llamas
el método de fábrica ofKeyframe()
para
obtén un objeto PropertyValuesHolder
. Una vez que tengas el objeto, podrás
Para obtener un animador, pasa el objeto PropertyValuesHolder
.
el objeto que se desea animar. En el siguiente fragmento de código, se muestra el proceso:
Kotlin
val kf0 = Keyframe.ofFloat(0f, 0f) val kf1 = Keyframe.ofFloat(.5f, 360f) val kf2 = Keyframe.ofFloat(1f, 0f) val pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2) ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation).apply { duration = 5000 }
Java
Keyframe kf0 = Keyframe.ofFloat(0f, 0f); Keyframe kf1 = Keyframe.ofFloat(.5f, 360f); Keyframe kf2 = Keyframe.ofFloat(1f, 0f); PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2); ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation); rotationAnim.setDuration(5000);
Cómo animar vistas
El sistema de animación de propiedades permite una animación optimizada de los objetos y las ofertas de View. algunas ventajas en comparación con el sistema de animación de vista. La vista un sistema de animación que transformó los objetos View cambiando la forma en que se dibujaban. Este era controlarse en el contenedor de cada vista, porque la vista en sí no tenía propiedades para manipular. Como resultado, la vista se animó, pero no se produjeron cambios en el objeto de vista. Esta lleva a un comportamiento como que un objeto sigue existiendo en su ubicación original, aunque no dibujada en una ubicación diferente en la pantalla. En Android 3.0, las propiedades nuevas y sus respectivos Se agregaron métodos get y set para eliminar este inconveniente.
El sistema de animación de propiedades
puede animar Vistas en la pantalla cambiando las propiedades reales en los objetos Vista. En
Además, los objetos View también llaman automáticamente a la clase invalidate()
.
para actualizar la pantalla cada vez que se cambian sus propiedades. Las nuevas propiedades de la clase View
que facilitan las animaciones de propiedades son las siguientes:
translationX
ytranslationY
: Estas propiedades controlan dónde se La vista se ubica como un delta a partir de sus coordenadas izquierda y superior, que se establecen por su diseño contenedor.rotation
,rotationX
yrotationY
: Estas propiedades controlar la rotación en 2D (propiedadrotation
) y en 3D alrededor del punto de pivote.scaleX
yscaleY
: Estas propiedades controlan el escalamiento en 2D de un Vista alrededor de su punto de pivote.pivotX
ypivotY
: Estas propiedades controlan la ubicación de la punto de pivote alrededor del cual se producen las transformaciones de rotación y escalamiento. De forma predeterminada, la tabla en el centro del objeto.x
yy
: Son propiedades de utilidad simples para describir el ubicación final de la vista en su contenedor, como una suma de los valores izquierdo y superior y los valores de traducciónX y de traducción Y.alpha
: Representa el valor de transparencia alfa en la vista. Este valor es 1 (opaco). de forma predeterminada, y el valor 0 representa la transparencia total (no visible).
Para animar una propiedad de un objeto View, como su valor de color o rotación, todo lo que necesitas es crear un animador de propiedades y especificar la propiedad View que quieres animar. Por ejemplo:
Kotlin
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f)
Java
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
Para obtener más información sobre cómo crear animadores, consulta las secciones sobre cómo animar con ValueAnimator y ObjectAnimator.
Cómo animar propiedades con ViewPropertyAnimator
ViewPropertyAnimator
proporciona una forma sencilla de animar varias
Propiedades de una View
en paralelo, con un solo Animator
subyacente
. Se comporta de forma muy parecida a una ObjectAnimator
, ya que modifica la
valores reales de las propiedades de la vista, pero es más eficaz al animar muchas propiedades en
una vez. Además, el código para usar ViewPropertyAnimator
es mucho más
sea más conciso y fácil de leer. Los siguientes fragmentos de código muestran las diferencias en el uso de varias
ObjectAnimator
, una sola
ObjectAnimator
y el ViewPropertyAnimator
cuando
animar simultáneamente las propiedades x
y y
de una vista.
Varios objetos de ObjectAnimator
Kotlin
val animX = ObjectAnimator.ofFloat(myView, "x", 50f) val animY = ObjectAnimator.ofFloat(myView, "y", 100f) AnimatorSet().apply { playTogether(animX, animY) start() }
Java
ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f); ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f); AnimatorSet animSetXY = new AnimatorSet(); animSetXY.playTogether(animX, animY); animSetXY.start();
Un ObjectAnimator
Kotlin
val pvhX = PropertyValuesHolder.ofFloat("x", 50f) val pvhY = PropertyValuesHolder.ofFloat("y", 100f) ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start()
Java
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f); PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f); ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start();
ViewPropertyAnimator
Kotlin
myView.animate().x(50f).y(100f)
Java
myView.animate().x(50f).y(100f);
Para obtener información más detallada sobre ViewPropertyAnimator
, consulta la documentación de
del blog
publicación.
Cómo declarar animaciones en XML
El sistema de animación de propiedades te permite declarar animaciones de propiedades con XML en lugar de hacerlo de forma programática. Cuando defines tus animaciones en XML, puedes reutilizarlas fácilmente en múltiples actividades y editar más fácilmente la secuencia de animación.
Para distinguir los archivos de animación que usan las nuevas APIs de Animation de propiedades de los que usan la
marco de trabajo heredado de animación de vistas,
A partir de Android 3.1, debes guardar los archivos en formato XML para las animaciones de propiedades en el directorio res/animator/
.
Las siguientes clases de animación de propiedades admiten la declaración XML con el las siguientes etiquetas XML:
ValueAnimator
-<animator>
ObjectAnimator
-<objectAnimator>
AnimatorSet
-<set>
Para encontrar los atributos que puedes usar en tu declaración XML, consulta Animación recursos. En el siguiente ejemplo, se reproducen los dos conjuntos de animaciones de objetos de forma secuencial, con el primer conjunto anidado reproduciendo dos animaciones de objetos juntas:
<set android:ordering="sequentially"> <set> <objectAnimator android:propertyName="x" android:duration="500" android:valueTo="400" android:valueType="intType"/> <objectAnimator android:propertyName="y" android:duration="500" android:valueTo="300" android:valueType="intType"/> </set> <objectAnimator android:propertyName="alpha" android:duration="500" android:valueTo="1f"/> </set>
A fin de ejecutar esta animación, tienes que aumentar los recursos XML en tu código para un objeto AnimatorSet
y, luego, establecer los objetos de destino para todas las animaciones antes de comenzar el conjunto de animación. Llamar a setTarget()
establece un único objeto de destino para todos los elementos secundarios del AnimatorSet
como método de conveniencia. El siguiente código muestra cómo hacer esto:
Kotlin
(AnimatorInflater.loadAnimator(myContext, R.animator.property_animator) as AnimatorSet).apply { setTarget(myObject) start() }
Java
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext, R.animator.property_animator); set.setTarget(myObject); set.start();
También puedes declarar un ValueAnimator
en XML, como
como se muestra en el siguiente ejemplo:
<animator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:valueType="floatType" android:valueFrom="0f" android:valueTo="-100f" />
Para usar el ValueAnimator
anterior en tu código, debes
debe aumentar el objeto, agregar un
AnimatorUpdateListener
,
obtener el valor actualizado de la animación y usarlo en una propiedad de una de tus vistas
como se muestra en el siguiente código:
Kotlin
(AnimatorInflater.loadAnimator(this, R.animator.animator) as ValueAnimator).apply { addUpdateListener { updatedAnimation -> textView.translationX = updatedAnimation.animatedValue as Float } start() }
Java
ValueAnimator xmlAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.animator); xmlAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator updatedAnimation) { float animatedValue = (float)updatedAnimation.getAnimatedValue(); textView.setTranslationX(animatedValue); } }); xmlAnimator.start();
Si deseas obtener información sobre la sintaxis XML para definir animaciones de propiedades, consulta Animación. recursos .
Posibles efectos en el rendimiento de la IU
Los animadores que actualizan la IU generan trabajo de renderización adicional para cada fotograma en en la que se ejecuta la animación. Por este motivo, usar animaciones que consumen muchos recursos puede afectar negativamente el rendimiento de la app.
El trabajo requerido para animar tu IU se agrega a la etapa de animación de la canalización de renderización. Puedes averiguar si tus animaciones tienen un impacto en la el rendimiento de tu app habilitando el Profile GPU Rendering. supervisar la etapa de animación. Para obtener más información, consulta Representación GPU de perfil .