A menudo, es necesario reposicionar los objetos que aparecen en pantalla debido a la interacción del usuario o al procesamiento tras bambalinas. En lugar de actualizar inmediatamente la posición del objeto, lo que hace que parpadee de un área a otra, usa una animación para moverlo de la posición inicial a su posición final.
Una forma en que Android te permite reposicionar tus objetos de visualización en la pantalla es con ObjectAnimator. Proporcionas la posición final en la que deseas colocar el objeto, además de la duración de la animación. También puedes usar interpoladores de tiempo para controlar la aceleración o desaceleración de la animación.
Cómo cambiar la posición de la vista con ObjectAnimator
La API de ObjectAnimator proporciona una forma de cambiar las propiedades de una vista con una duración especificada.
Contiene métodos estáticos para crear instancias de ObjectAnimator, según el tipo de atributo que estás animando. Cuando reposiciones tus vistas en la pantalla, usa los atributos translationX y translationY.
A continuación, puedes ver un ejemplo de un ObjectAnimator que mueve la vista a una posición 100 píxeles desde la izquierda de la pantalla en 2 segundos:
Kotlin
ObjectAnimator.ofFloat(view, "translationX", 100f).apply { duration = 2000 start() }
Java
ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationX", 100f); animation.setDuration(2000); animation.start();
En este ejemplo, se usa el método ObjectAnimator.ofFloat(), ya que los valores de traducción tienen que ser flotantes. El primer parámetro es la vista que deseas animar. El segundo parámetro es la propiedad que estás animando. Como la vista debe moverse de forma horizontal, se utiliza la propiedad translationX. El último parámetro es el valor final de la animación. En este ejemplo, el valor 100 indica una posición que se encuentra a muchos píxeles de la izquierda de la pantalla.
En el siguiente método, se especifica cuánto tarda la animación, en milisegundos. En este ejemplo, la animación se ejecuta durante 2 segundos (2,000 milisegundos).
El último método hace que se ejecute la animación, lo que actualiza la posición de la vista en la pantalla.
Para obtener más información sobre el uso de ObjectAnimator, consulta Cómo animar propiedades con ObjectAnimator.
Cómo agregar movimientos curvos
Si bien conviene usarlo, ObjectAnimator reposiciona la vista de manera predeterminada a lo largo de una línea recta entre los puntos de inicio y de finalización. Material Design usa curvas para el movimiento espacial de los objetos en la pantalla y el tiempo de una animación. Usar movimientos curvos le da a tu app una mayor sensación de realidad y, al mismo tiempo, hace que tus animaciones sean más interesantes.
Cómo definir tu propia trayectoria
La clase ObjectAnimator tiene constructores que te permiten animar coordenadas usando dos o más propiedades a la vez junto con una ruta. Por ejemplo, el siguiente animador usa un objeto Path para animar las propiedades X e Y de una vista:
Kotlin
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { val path = Path().apply { arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true) } val animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path).apply { duration = 2000 start() } } else { // Create animator without using curved path }
Java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Path path = new Path(); path.arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true); ObjectAnimator animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path); animator.setDuration(2000); animator.start(); } else { // Create animator without using curved path }
La animación de arco se ve de la siguiente manera:
Figura 1: Animación de una ruta curva.
Un Interpolator es una implementación de una curva de aceleración. Consulta la documentación de Material Design para obtener más información sobre el concepto de curvas de aceleración. Un Interpolator define cómo se calculan los valores específicos de una animación en función del tiempo. El sistema proporciona recursos XML para las tres curvas básicas en la especificación de Material Design:
@interpolator/fast_out_linear_in.xml@interpolator/fast_out_slow_in.xml@interpolator/linear_out_slow_in.xml
Cómo usar PathInterpolator
La clase PathInterpolator es un interpolador que se introdujo en Android 5.0 (API 21). Se basa en una curva Bézier o un objeto Path. Los ejemplos de Android en la documentación de Material Design sobre aceleración usan PathInterpolator.
PathInterpolator tiene constructores basados en diferentes tipos de curvas de Bézier.
Todas las curvas de Bézier tienen puntos de inicio y finalización fijos en (0,0) y (1,1), respectivamente. Los demás argumentos del constructor dependen del tipo de curva de Bézier que se cree.
Por ejemplo, para una curva de Bézier cuadrática, solo se necesitan las coordenadas X e Y de un punto de control:
Kotlin
val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { PathInterpolator(0.67f, 0.33f) } else { LinearInterpolator() }
Java
Interpolator myInterpolator = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { myInterpolator = new PathInterpolator(0.67f, 0.33f); } else { myInterpolator = new LinearInterpolator(); }
Esto produce una curva de aceleración que comienza rápidamente y se desacelera a medida que se acerca al final.
Del mismo modo, el constructor de Bézier cúbico tiene puntos de inicio y finalización fijos, pero requiere dos puntos de control:
Kotlin
val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f) } else { LinearInterpolator() }
Java
Interpolator myInterpolator = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { myInterpolator = new PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f); } else { myInterpolator = new LinearInterpolator(); }
Esta es una implementación de la curva de aceleración desaceleración enfatizada de Material Design.
Para tener un mayor control, se puede usar un Path arbitrario para definir la curva:
Kotlin
val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { val path = Path().apply { moveTo(0.0f, 0.0f) cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f) } PathInterpolator(path) } else { LinearInterpolator() }
Java
Interpolator myInterpolator = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Path path = new Path(); path.moveTo(0.0f, 0.0f); path.cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f); myInterpolator = new PathInterpolator(path); } else { myInterpolator = new LinearInterpolator(); }
Esto produce la misma curva de aceleración que el ejemplo de Bézier cúbico, pero usa un Path en su lugar.
También puedes definir un interpolador para la ruta de acceso como un recurso XML:
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:controlX1="0.5"
android:controlY1="0.7"
android:controlX2="0.1f"
android:controlY2="1.0f"/>
Una vez que crees un objeto PathInterpolator, puedes pasárselo al método Animator.setInterpolator(). El Animator usa el interpolador para determinar la curva de la trayectoria o el tiempo cuando se lo inicia.
Kotlin
val animation = ObjectAnimator.ofFloat(view, "translationX", 100f).apply { interpolator = myInterpolator start() }
Java
ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationX", 100f); animation.setInterpolator(myInterpolator); animation.start();