Una transición personalizada permite crear una animación que no está disponible en ninguna de las clases de transición integradas. Por ejemplo, puedes definir una transición personalizada que cambie el color en primer plano de los campos de texto y entrada a gris para indicar que los campos están inhabilitados en la pantalla nueva. Este tipo de cambio ayuda a los usuarios a ver los campos que inhabilitaste.
Una transición personalizada, al igual que uno de los tipos de transición integradas, aplica animaciones a las vistas secundarias de las escenas inicial y final. Sin embargo, a diferencia de los tipos de transición integrados, debes proporcionar el código que captura los valores de propiedad y genera animaciones. También puedes definir un subconjunto de vistas objetivo para la animación.
En esta página, se detalla cómo capturar valores de propiedad y generar animaciones para crear transiciones personalizadas.
Cómo extender la clase de transición
Para crear una transición personalizada, agrega una clase a tu proyecto que extienda la clase Transition
y anula las funciones que se muestran en el siguiente fragmento:
Kotlin
class CustomTransition : Transition() { override fun captureStartValues(transitionValues: TransitionValues) {} override fun captureEndValues(transitionValues: TransitionValues) {} override fun createAnimator( sceneRoot: ViewGroup, startValues: TransitionValues?, endValues: TransitionValues? ): Animator? {} }
Java
public class CustomTransition extends Transition { @Override public void captureStartValues(TransitionValues values) {} @Override public void captureEndValues(TransitionValues values) {} @Override public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, TransitionValues endValues) {} }
En las siguientes secciones, se explica cómo anular estas funciones.
Cómo capturar valores de propiedades de vista
Las animaciones de transición utilizan el sistema de animación de propiedades que se describe en Descripción general de la animación de propiedades. Las animaciones de propiedades cambian una propiedad de vista de un valor inicial a uno final durante un período específico, por lo que el framework debe tener el valor inicial y el final de la propiedad para crear la animación.
Sin embargo, una animación de propiedad suele requerir solo un pequeño subconjunto de todos los valores de propiedad de la vista. Por ejemplo, una animación de color requiere valores de propiedad de color, mientras que una animación de movimiento requiere valores de propiedad de posición. Como los valores de propiedad necesarios para una animación son específicos de una transición, el framework de transiciones no proporciona todos los valores de propiedad a una transición. En cambio, el framework invoca funciones de devolución de llamada que permiten que una transición capture solo los valores de propiedad que necesita y los almacene en el framework.
Cómo capturar valores iniciales
Para pasar los valores de vista iniciales al framework, implementa la función captureStartValues(transitionValues)
. El framework llama a esta función para cada vista en la escena inicial. El argumento de la función es un objeto TransitionValues
que contiene una referencia a la vista y una instancia Map
en la que puedes almacenar los valores de vista que desees. En tu implementación, recupera esos valores de propiedad y pásalos de framework de trabajo almacenándolos en el mapa.
Para garantizar que la clave de un valor de propiedad no entre en conflicto con otras claves TransitionValues
, usa el siguiente esquema de nombres:
package_name:transition_name:property_name
El siguiente fragmento muestra una implementación de la función captureStartValues()
:
Kotlin
class CustomTransition : Transition() { // Define a key for storing a property value in // TransitionValues.values with the syntax // package_name:transition_class:property_name to avoid collisions private val PROPNAME_BACKGROUND = "com.example.android.customtransition:CustomTransition:background" override fun captureStartValues(transitionValues: TransitionValues) { // Call the convenience method captureValues captureValues(transitionValues) } // For the view in transitionValues.view, get the values you // want and put them in transitionValues.values private fun captureValues(transitionValues: TransitionValues) { // Get a reference to the view val view = transitionValues.view // Store its background property in the values map transitionValues.values[PROPNAME_BACKGROUND] = view.background } ... }
Java
public class CustomTransition extends Transition { // Define a key for storing a property value in // TransitionValues.values with the syntax // package_name:transition_class:property_name to avoid collisions private static final String PROPNAME_BACKGROUND = "com.example.android.customtransition:CustomTransition:background"; @Override public void captureStartValues(TransitionValues transitionValues) { // Call the convenience method captureValues captureValues(transitionValues); } // For the view in transitionValues.view, get the values you // want and put them in transitionValues.values private void captureValues(TransitionValues transitionValues) { // Get a reference to the view View view = transitionValues.view; // Store its background property in the values map transitionValues.values.put(PROPNAME_BACKGROUND, view.getBackground()); } ... }
Cómo capturar valores finales
El framework llama a la función captureEndValues(TransitionValues)
una vez para cada vista de destino en la escena final. En todos los demás aspectos, captureEndValues()
funciona igual que captureStartValues()
.
En el siguiente fragmento de código, se muestra una implementación de la función captureEndValues()
:
Kotlin
override fun captureEndValues(transitionValues: TransitionValues) { captureValues(transitionValues) }
Java
@Override public void captureEndValues(TransitionValues transitionValues) { captureValues(transitionValues); }
En este ejemplo, las funciones captureStartValues()
y captureEndValues()
invocan a captureValues()
para recuperar y almacenar valores. La propiedad de vista que recupera captureValues()
es la misma, pero tiene valores diferentes en las escenas inicial y final. El framework mantiene mapas separados para los estados inicial y final de una vista.
Cómo crear un animador personalizado
Para animar los cambios en una vista entre su estado en la escena inicial y su estado en la escena final, proporciona un animador anulando la función createAnimator()
. Cuando el framework llama a esta función, pasa en la vista raíz de la escena y los objetos TransitionValues
que contienen los valores inicial y final que capturaste.
La cantidad de veces que el framework llama a la función createAnimator()
depende de los cambios que se producen entre las escenas inicial y final.
Por ejemplo, considera una animación de fundido de salida o de entrada implementada como una transición personalizada. Si la escena inicial tiene cinco destinos, de los cuales dos se quitan de la escena final, y la escena final tiene los tres destinos de la escena inicial más un destino nuevo, el framework llama a createAnimator()
seis veces.
Tres de las llamadas animan el desvanecimiento de los objetivos que permanecen en ambos objetos de escena. Dos llamadas más animan la atenuación de los objetivos quitados de la escena final. Una llamada anima la atenuación del nuevo objetivo en la escena final.
En el caso de las vistas de destino que existen en las escenas inicial y final, el framework proporciona un objeto TransitionValues
para los argumentos startValues
y endValues
. En el caso de las vistas de destino que solo existen en la escena inicial o final, el framework proporciona un objeto TransitionValues
para el argumento correspondiente y null
para el otro.
Para implementar la función createAnimator(ViewGroup, TransitionValues, TransitionValues)
cuando creas una transición personalizada, usa los valores de propiedad de vista que capturaste para crear un objeto Animator
y devolverlo al framework. Para ver un ejemplo de implementación, consulta la clase ChangeColor
en el ejemplo de
CustomTransition. Si quieres obtener más información sobre los animadores de propiedades, consulta Animación de propiedades.
Cómo aplicar una transición personalizada
Las transiciones personalizadas funcionan igual que las transiciones integradas. Puedes aplicar una transición personalizada con un administrador de transiciones, como se describe en Aplica una transición.