Basado en la física El movimiento está impulsado por la fuerza. La fuerza del resorte es una de las fuerzas que guía interactividad y movimiento. Una fuerza de resorte tiene las siguientes propiedades: amortiguación y rigidez. En una animación basada en resortes, el valor y la se calculan en función de la fuerza de resorte que se aplica a cada marco.
Si quieres que las animaciones de tu app se ralenticen en una sola dirección, considera usar un modelo de fricción animación de deslizamiento en su lugar.
Ciclo de vida de una animación de resorte
En una animación basada en resortes, el elemento SpringForce
te permite personalizar la rigidez del resorte, su proporción de amortiguamiento y su
en la posición final. En cuanto comienza la animación, se actualiza la fuerza de resorte
el valor de la animación y la velocidad en cada fotograma. La animación continúa
hasta que la fuerza de resorte alcanza un equilibrio.
Por ejemplo, si arrastras el ícono de una app por la pantalla y luego lo sueltas levantando el dedo del icono, este se devuelve a su posición original gracias a una fuerza invisible pero familiar.
En la figura 1, se muestra un efecto de resorte similar. El signo más (+) en el el centro del círculo indica la fuerza aplicada mediante un gesto táctil.
![Liberación del resorte](https://developer.android.com/static/images/guide/topics/graphics/spring-release.gif?authuser=9&hl=es)
Cómo crear una animación de resorte
Los pasos generales para compilar una animación de resorte para tu aplicación son de la siguiente manera:
- Cómo agregar la biblioteca de compatibilidad Debes agregar la biblioteca de compatibilidad a tu proyecto para usar las clases de animación de resorte.
- Crea una animación de resorte:
El paso principal es crear una instancia del
SpringAnimation
y configura el movimiento parámetros de comportamiento. - Registra objetos de escucha(opcional):
Cómo registrar objetos de escucha para detectar cambios en el ciclo de vida de la animación y la animación
actualizaciones de valores.
Nota: El objeto de escucha de actualizaciones debe ser solo se registran si necesitas una actualización por fotograma en el valor de la animación cambios. Un objeto de escucha de actualizaciones evita que la animación que se ejecuta en un subproceso independiente.
- (Opcional) Quita los objetos de escucha: Quita los objetos de escucha que ya no estén en uso.
- Configura un valor de inicio(opcional): Personaliza el valor de inicio de la animación.
- Configura un rango de valores(opcional): Establece el rango de valores de la animación para restringir los valores dentro del rango mínimo y máximo.
- Configura la velocidad de inicio(opcional): Establece la velocidad de inicio de la animación.
- (Opcional) Establece las propiedades del resorte: Establece la proporción de amortiguamiento y la rigidez del resorte.
- (Opcional) Crea un resorte personalizado: Crea un resorte personalizado en caso de que no quieras usar el predeterminado o quieres usar un resorte común durante toda la animación.
- Inicia la animación: Inicia la animación de resorte.
- (Opcional) Cancela la animación: Cancela la animación en caso de que el usuario salga repentinamente de la app o la vista. se vuelve invisible.
En las siguientes secciones, se analizan los pasos generales para construir un resorte animación en detalle.
Cómo agregar la biblioteca de compatibilidad
Para usar la biblioteca de compatibilidad basada en la física, debes agregarla a tu proyecto. de la siguiente manera:
- Abre el archivo
build.gradle
del módulo de tu app. Agrega la biblioteca de compatibilidad a la sección
dependencies
.Groovy
dependencies { def dynamicanimation_version = '1.0.0' implementation "androidx.dynamicanimation:dynamicanimation:$dynamicanimation_version" }
Kotlin
dependencies { val dynamicanimation_version = "1.0.0" implementation("androidx.dynamicanimation:dynamicanimation:$dynamicanimation_version") }
Para ver las versiones actuales de esta biblioteca, consulta la información sobre Animación dinámica en la página de versiones.
Cómo crear una animación de resorte
La clase SpringAnimation
te permite crear
una animación de resorte para un objeto. Para crear una animación de resorte, debes hacer lo siguiente:
Crea una instancia de SpringAnimation
.
y proporciona un objeto, la propiedad de un objeto que quieres animar y una
la posición final opcional del resorte
en la que quieres que se apoye la animación.
Nota: Al momento de crear una animación de resorte, la del resorte es opcional. Sin embargo, debe definirse antes de iniciar la animación.
Kotlin
val springAnim = findViewById<View>(R.id.imageView).let { img -> // Setting up a spring animation to animate the view’s translationY property with the final // spring position at 0. SpringAnimation(img, DynamicAnimation.TRANSLATION_Y, 0f) }
Java
final View img = findViewById(R.id.imageView); // Setting up a spring animation to animate the view’s translationY property with the final // spring position at 0. final SpringAnimation springAnim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y, 0);
La animación basada en resortes puede animar vistas en la pantalla cambiando el propiedades reales en los objetos View. Las siguientes vistas están disponibles en el sistema:
ALPHA
: Representa la transparencia alfa en la vista. El valor es 1 (opaco) en es predeterminada, y el valor 0 representa la transparencia total (no visible).TRANSLATION_X
,TRANSLATION_Y
yTRANSLATION_Z
: Estos Las propiedades controlan dónde se ubica la vista como un delta de su izquierda coordenada superior y la elevación, que se establecen por su diseño contenedor.TRANSLATION_X
describe la coordenada izquierda.TRANSLATION_Y
describe la coordenada superior.TRANSLATION_Z
describe la profundidad de la vista en relación con su elevación.
ROTATION
,ROTATION_X
yROTATION_Y
: Estos Las propiedades controlan la rotación en 2D (propiedadrotation
) y 3D alrededor del punto de pivote.SCROLL_X
ySCROLL_Y
: Estos Las propiedades indican el desplazamiento de la fuente izquierda y el borde superior. en píxeles. También indica la posición en términos de cuánto cuesta la página. desplazado.SCALE_X
ySCALE_Y
: Estos controlan la escala en 2D de una vista alrededor de su punto de pivote.X
,Y
yZ
: Estos son datos básicos propiedades de utilidad para describir la ubicación final de la vista en su contenedor.X
es una suma de el valor de la izquierda yTRANSLATION_X
.Y
es una suma de el valor superior yTRANSLATION_Y
.Z
es una suma de valor de elevación yTRANSLATION_Z
.
Cómo registrar objetos de escucha
La clase DynamicAnimation
proporciona dos
objetos de escucha: OnAnimationUpdateListener
y OnAnimationEndListener
.
Estos objetos de escucha escuchan las actualizaciones en animación, como cuando hay una
el valor de la animación y cuando esta llega a su fin.
OnAnimationUpdateListener
Cuando quieres animar varias vistas para crear una animación encadenada, debes
puede configurar OnAnimationUpdateListener
para recibir una devolución de llamada cada vez que haya un cambio en la vista actual
propiedad. La devolución de llamada notifica a la otra vista para que actualice su posición del resorte
según el cambio generado en la propiedad de la vista actual. Para registrar el
objeto de escucha, realiza los siguientes pasos:
-
Llama al
addUpdateListener()
y adjuntar el objeto de escucha a la animación.Nota: Debes registrar la actualización. del objeto de escucha antes de que comience la animación. Sin embargo, el objeto de escucha de actualizaciones debe ser solo se registran si necesitas una actualización por fotograma en el valor de la animación cambios. Un objeto de escucha de actualizaciones evita que la animación que se ejecuta en un subproceso independiente.
-
Anula
onAnimationUpdate()
para notificar al emisor sobre el cambio en el objeto actual. El siguiente código de muestra ilustra el uso general deOnAnimationUpdateListener
Kotlin
// Setting up a spring animation to animate the view1 and view2 translationX and translationY properties val (anim1X, anim1Y) = findViewById<View>(R.id.view1).let { view1 -> SpringAnimation(view1, DynamicAnimation.TRANSLATION_X) to SpringAnimation(view1, DynamicAnimation.TRANSLATION_Y) } val (anim2X, anim2Y) = findViewById<View>(R.id.view2).let { view2 -> SpringAnimation(view2, DynamicAnimation.TRANSLATION_X) to SpringAnimation(view2, DynamicAnimation.TRANSLATION_Y) } // Registering the update listener anim1X.addUpdateListener { _, value, _ -> // Overriding the method to notify view2 about the change in the view1’s property. anim2X.animateToFinalPosition(value) } anim1Y.addUpdateListener { _, value, _ -> anim2Y.animateToFinalPosition(value) }
Java
// Creating two views to demonstrate the registration of the update listener. final View view1 = findViewById(R.id.view1); final View view2 = findViewById(R.id.view2); // Setting up a spring animation to animate the view1 and view2 translationX and translationY properties final SpringAnimation anim1X = new SpringAnimation(view1, DynamicAnimation.TRANSLATION_X); final SpringAnimation anim1Y = new SpringAnimation(view1, DynamicAnimation.TRANSLATION_Y); final SpringAnimation anim2X = new SpringAnimation(view2, DynamicAnimation.TRANSLATION_X); final SpringAnimation anim2Y = new SpringAnimation(view2, DynamicAnimation.TRANSLATION_Y); // Registering the update listener anim1X.addUpdateListener(new DynamicAnimation.OnAnimationUpdateListener() { // Overriding the method to notify view2 about the change in the view1’s property. @Override public void onAnimationUpdate(DynamicAnimation dynamicAnimation, float value, float velocity) { anim2X.animateToFinalPosition(value); } }); anim1Y.addUpdateListener(new DynamicAnimation.OnAnimationUpdateListener() { @Override public void onAnimationUpdate(DynamicAnimation dynamicAnimation, float value, float velocity) { anim2Y.animateToFinalPosition(value); } });
OnAnimationEndListener
OnAnimationEndListener
notifica el final de una animación. Puedes configurar el objeto de escucha para que reciba
cada vez que la animación alcanza el equilibrio o se cancela. Para
para registrar el objeto de escucha, sigue estos pasos:
-
Llama al
addEndListener()
y adjuntar el objeto de escucha a la animación. -
Anula
onAnimationEnd()
método para recibir una notificación cada vez que una animación alcanza el equilibrio o se cancela.
Cómo quitar objetos de escucha
Para dejar de recibir devoluciones de llamada de actualización y de finalización de la animación, haz lo siguiente:
llamar a removeUpdateListener()
y removeEndListener()
.
de forma manual, respectivamente.
Cómo establecer el valor de inicio de la animación
Para establecer el valor de inicio de la animación, llama al
setStartValue()
y pasa el valor de inicio de la animación. Si no estableces
valor de inicio, la animación usa el valor actual de la propiedad del objeto
como valor inicial.
Cómo establecer un rango de valores de la animación
Puedes establecer los valores de animación mínimos y máximos cuando desees restringir el valor de la propiedad a un cierto rango. También ayuda a controlar rango en caso de que animes propiedades que tienen un rango intrínseco, como alfa (de 0 a 1).
-
Para establecer el valor mínimo, llama al
setMinValue()
y pasa el valor mínimo de la propiedad. -
Para establecer el valor máximo, llama al
setMaxValue()
. y pasa el valor máximo de la propiedad.
Ambos métodos muestran la animación para la que se establece el valor.
Nota: Si estableciste el valor de inicio y definas un rango de valores de la animación, asegúrate de que el valor de inicio esté dentro del el rango de valores mínimo y máximo.
Cómo establecer la velocidad de inicio
La velocidad de inicio define la velocidad a la que cambia la propiedad de la animación al principio de la animación. La velocidad de inicio predeterminada se estableció en cero píxeles por segundo. Puedes establecer la velocidad ya sea con la velocidad del tacto con gestos o con un valor fijo como velocidad inicial. Si eliges proporcionan un valor fijo, te recomendamos que definas el valor en dp por segundo y y convertirlo en píxeles por segundo. Cómo definir el valor en dp por segundo permite que la velocidad sea independiente de la densidad y los factores de forma. Para ver más sobre la conversión de valores a píxeles por segundo, consulta la Cómo convertir dp por segundo a píxeles por segundo sección.
Para establecer la velocidad, llama al
setStartVelocity()
y pasa la velocidad en píxeles por segundo. El método devuelve
el objeto de fuerza de resorte en el que se establece la velocidad.
Nota: Usa la
GestureDetector.OnGestureListener
o el
Métodos de clase VelocityTracker
para recuperar y procesar
la velocidad de los gestos táctiles.
Kotlin
findViewById<View>(R.id.imageView).also { img -> SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply { … // Compute velocity in the unit pixel/second vt.computeCurrentVelocity(1000) val velocity = vt.yVelocity setStartVelocity(velocity) } }
Java
final View img = findViewById(R.id.imageView); final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y); … // Compute velocity in the unit pixel/second vt.computeCurrentVelocity(1000); float velocity = vt.getYVelocity(); anim.setStartVelocity(velocity);
Cómo convertir dp por segundo a píxeles por segundo
La velocidad de un resorte debe expresarse en píxeles por segundo. Si eliges proporcionar
el valor fijo como el inicio de la velocidad, proporciona el valor en dp por segundo
y luego convertirlo a píxeles por segundo. Para las conversiones, usa el
applyDimension()
de la clase TypedValue
. Consulta las
siguiente código de muestra:
Kotlin
val pixelPerSecond: Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpPerSecond, resources.displayMetrics)
Java
float pixelPerSecond = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpPerSecond, getResources().getDisplayMetrics());
Cómo establecer las propiedades del resorte
La clase SpringForce
define el método get
y los métodos set para cada una de las propiedades del resorte, como el
proporción y rigidez. Para establecer las propiedades del resorte, es importante
recuperar el objeto de fuerza del resorte
o crear una fuerza de resorte personalizada
puedes establecer las propiedades. Para obtener más información sobre cómo crear un
fuerza de resorte, consulta la
Cómo crear una fuerza de resorte personalizada
sección.
Sugerencia: Mientras usas los métodos set, puedes crea una cadena de métodos, ya que todos los métodos set devuelven la fuerza del resorte .
Proporción de amortiguamiento
La proporción de amortiguamiento describe una reducción gradual en la oscilación de un resorte. De con la proporción de amortiguamiento, puedes definir la rapidez con la que de un rebote al siguiente. Existen cuatro formas diferentes de amortiguar un primavera:
- El sobreamortiguamiento se produce cuando la proporción de amortiguamiento es mayor que uno. Te permite el objeto regresará suavemente a la posición de reposo.
- El amortiguamiento crítico se produce cuando la proporción de amortiguamiento es igual a uno. Te permite el objeto regresa a la posición de reposo en el menor tiempo posible.
- El subamortiguamiento se produce cuando la proporción de amortiguamiento es menor que uno. Te permite el objeto se sobrepasa varias veces pasando la posición de reposo y, luego, alcanza gradualmente la posición de reposo.
- El no amortiguamiento se produce cuando la proporción de amortiguamiento es igual a cero. Le permite a la oscilarán para siempre.
Para agregar la proporción de amortiguamiento al resorte, sigue estos pasos:
-
Llama al
getSpring()
para recuperar el resorte y agregar la proporción de amortiguamiento. -
Llama al
setDampingRatio()
y pasa la proporción de amortiguamiento que quieres agregar al resorte. El muestra el objeto de fuerza de resorte en el que se estableció la proporción de amortiguamiento.Nota: La proporción de amortiguamiento debe ser un un número no negativo. Si estableces la proporción de amortiguamiento en cero, el resorte nunca alcancen la posición de reposo. En otras palabras, oscilará de manera permanente.
Las siguientes constantes de proporción de amortiguamiento se encuentran disponibles en el sistema:
DAMPING_RATIO_HIGH_BOUNCY
DAMPING_RATIO_MEDIUM_BOUNCY
DAMPING_RATIO_LOW_BOUNCY
DAMPING_RATIO_NO_BOUNCY
Figura 2: Rebote alto
Figura 3: Rebote medio
Figura 4: Rebote bajo
Figura 5: Sin rebote
La proporción de amortiguamiento predeterminada se establece en DAMPING_RATIO_MEDIUM_BOUNCY
.
Kotlin
findViewById<View>(R.id.imageView).also { img -> SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply { … // Setting the damping ratio to create a low bouncing effect. spring.dampingRatio = SpringForce.DAMPING_RATIO_LOW_BOUNCY … } }
Java
final View img = findViewById(R.id.imageView); final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y); … // Setting the damping ratio to create a low bouncing effect. anim.getSpring().setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY); …
Rigidez
La rigidez define la constante de resorte, que mide la fuerza del a la primavera. Un resorte rígido aplica más fuerza al objeto que está unido cuando el resorte no está en la posición de reposo. Para agregar la rigidez al resorte, sigue estos pasos:
-
Llama al
getSpring()
para recuperar el resorte y agregar la rigidez. -
Llama al
setStiffness()
y pasa el valor de rigidez que quieres agregar al resorte. El muestra el objeto de fuerza de resorte en el que se estableció la rigidez.Nota: La rigidez debe ser una positivo.
Las siguientes constantes de rigidez están disponibles en el sistema:
Figura 6: Rigidez alta
Figura 7: Rigidez media
Figura 8: Rigidez baja
Figura 9: Rigidez muy baja
La rigidez predeterminada se establece en STIFFNESS_MEDIUM
.
Kotlin
findViewById<View>(R.id.imageView).also { img -> SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply { … // Setting the spring with a low stiffness. spring.stiffness = SpringForce.STIFFNESS_LOW … } }
Java
final View img = findViewById(R.id.imageView); final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y); … // Setting the spring with a low stiffness. anim.getSpring().setStiffness(SpringForce.STIFFNESS_LOW); …
Cómo crear una fuerza de resorte personalizada
Puedes crear una fuerza de resorte personalizada como alternativa al uso de la fuerza de la fuerza del resorte. La fuerza de resorte personalizada te permite compartir la misma fuerza de resorte en múltiples animaciones de resorte. Una vez que hayas creado el resorte puedes establecer propiedades como la proporción de amortiguamiento y la rigidez.
-
Crearás un objeto
SpringForce
.SpringForce force = new SpringForce();
-
Llama a los métodos correspondientes para asignar las propiedades. También puedes
crear una cadena de métodos.
force.setDampingRatio(DAMPING_RATIO_LOW_BOUNCY).setStiffness(STIFFNESS_LOW);
-
Llama al
setSpring()
para establecer el resorte en la animación.setSpring(force);
Iniciar la animación
Existen dos maneras de iniciar una animación de resorte: llamando al
start()
o llamando al
animateToFinalPosition()
. Ambos métodos deben ser llamados en el subproceso principal.
animateToFinalPosition()
realiza dos tareas:
- Establece la posición final del resorte.
- Inicia la animación si no ha comenzado.
Como el método actualiza la posición final del resorte y comienza el
animación si es necesario, puedes llamar a este método en cualquier momento para cambiar el curso
de una animación. Por ejemplo, en una animación de resorte encadenada, la animación
de una vista depende de otra. Para una animación de este tipo, es más
conveniente usar la
animateToFinalPosition()
. Cuando usas este método en una animación de resorte encadenada, no necesitas
si la animación que quieres actualizar
a continuación se está ejecutando en ese momento.
La Figura 10 ilustra una animación de resorte encadenada, donde la animación de uno depende de otra vista.
![Demostración de resortes en cadena](https://developer.android.com/static/images/guide/topics/graphics/spring_chain.gif?authuser=9&hl=es)
Para usar animateToFinalPosition()
, sigue estos pasos:
, llama al método
animateToFinalPosition()
y pasa la posición de reposo del resorte. También puedes configurar el resto
posición del resorte al llamar al
setFinalPosition()
.
El método start()
hace lo siguiente:
No establecer de inmediato el valor de la propiedad en el valor inicial. La propiedad
el valor cambia con cada pulso de la animación, lo que ocurre antes del pase de dibujo.
Como resultado, los cambios se reflejan en el siguiente fotograma, como si
los valores se establecen de inmediato.
Kotlin
findViewById<View>(R.id.imageView).also { img -> SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply { … // Starting the animation start() … } }
Java
final View img = findViewById(R.id.imageView); final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y); … // Starting the animation anim.start(); …
Cómo cancelar la animación
Puedes cancelar la animación o puedes omitirla hasta el final. Una situación ideal donde debes cancelar u omitir hasta el final de la acción es cuando un usuario requiere que la animación finalice inmediatamente. Este es principalmente cuando un usuario sale de una app de manera abrupta o la vista se vuelve invisible.
Existen dos métodos que puedes usar para finalizar la animación.
El método cancel()
finaliza la animación en el valor en el que se encuentra. El
Método skipToEnd()
salta la animación hasta el valor final y luego la finaliza.
Antes de terminar la animación, es importante verificar primero el
estado del manantial. Si el estado no está amortiguado, la animación nunca puede alcanzar
la posición de reposo.
Para verificar el estado del resorte, llama al
canSkipToEnd()
. Si
el resorte está amortiguado, el método muestra true
; de lo contrario,
false
Una vez que conozcas el estado del resorte, podrás finalizar una animación con
mediante
skipToEnd()
o
cancel()
. El
Método cancel()
debe llamarse solo en el subproceso principal.
Nota: En general, el
Causas del método skipToEnd()
un salto visual.