El framework de transición de Android te permite animar todo tipo de movimiento en tu IU, proporcionando los diseños inicial y final. Puedes seleccionar qué tipo de animación deseas, como atenuar las vistas. hacia adentro o afuera, o para cambiar los tamaños de las vistas, y el framework de transición determina cómo animar desde el diseño inicial al diseño final.
En el marco de trabajo de transición, se incluyen las siguientes funciones:
- Animaciones a nivel de grupo: aplicar efectos de animación a todas las vistas en una jerarquía de vistas.
- Animaciones integradas: Usa animaciones predefinidas para efectos comunes, como fundido de salida o movimiento.
- Compatibilidad con archivos de recursos: cargar jerarquías de vistas y animaciones integradas desde archivos de recursos de diseño.
- Devoluciones de llamada de ciclo de vida: Recibir devoluciones de llamada que proporcionan control sobre la animación y la jerarquía el proceso de cambio.
Para ver código de muestra con animación entre los cambios de diseño, consulta BasicTransition.
El proceso básico para animar entre dos diseños es el siguiente:
- Crea un objeto
Scene
para el elemento en el diseño inicial y el final. Sin embargo, la escena del diseño inicial está a menudo se determina automáticamente a partir del diseño actual. - Crea un
Transition
. para definir el tipo de animación que deseas. - Llamada
TransitionManager.go()
: y el sistema ejecuta la animación para cambiar los diseños.
El diagrama de la figura 1 ilustra la relación entre tus diseños, escenas, la transición y la animación final.
Crea una escena
Las escenas almacenan el estado de una jerarquía de vistas, incluidas todas sus vistas y sus los valores de las propiedades. El framework de transiciones puede ejecutar animaciones entre un y una escena final.
Puedes crear escenas a partir de un diseño archivo de recursos o de un grupo de vistas en tu código. Sin embargo, el la escena inicial de la transición suele determinarse automáticamente IU actual.
Una escena también puede definir sus propias acciones que se ejecutan cuando realizas un cambio de escena. Esta función es útil para borrar la configuración de las vistas después de la transición a una escena.
Cómo crear una escena a partir de un recurso de diseño
Puedes crear una instancia de Scene
directamente desde un recurso de diseño.
. Usa esta técnica cuando la mayoría de la jerarquía de vistas en el archivo sea estática.
La escena resultante representa el estado de la jerarquía de vistas en el momento en que
creó la instancia Scene
. Si cambias la jerarquía de vistas,
recrear la escena. El framework crea la escena a partir de toda la vista
jerarquía en el archivo. No puedes crear una escena a partir de una parte de un archivo de diseño.
Para crear una instancia de Scene
a partir de un archivo de recursos de diseño, recupera
la raíz de la escena de tu diseño como una
ViewGroup
Luego, llama al
Scene.getSceneForLayout()
con la raíz de escena y el ID de recurso del archivo de diseño que
contiene la jerarquía de vistas de la escena.
Cómo definir diseños para escenas
En los fragmentos de código del resto de esta sección, se muestra cómo crear dos
diferentes escenas con el mismo elemento raíz de escena. Los fragmentos también demuestran
que puedes cargar varios objetos Scene
no relacionados sin implicar que
están relacionadas entre sí.
En el ejemplo, se incluyen las siguientes definiciones de diseño:
- Diseño principal de una actividad con una etiqueta de texto y un elemento secundario
FrameLayout
- Un objeto
ConstraintLayout
para el elemento primera escena con dos campos de texto. - Un
ConstraintLayout
para la segunda escena con los mismos dos campos de texto en en un orden diferente.
El ejemplo está diseñado para que toda la animación ocurra en el campo secundario del diseño principal de la actividad. La etiqueta de texto en el diseño principal permanece estática.
El diseño principal de la actividad se define de la siguiente manera:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/master_layout"> <TextView android:id="@+id/title" ... android:text="Title"/> <FrameLayout android:id="@+id/scene_root"> <include layout="@layout/a_scene" /> </FrameLayout> </LinearLayout>
Esta definición de diseño contiene un campo de texto y un elemento FrameLayout
secundario para el
raíz de escena. El diseño de la primera escena se incluye en el archivo de diseño principal.
Esto permite que la app lo muestre como parte de la interfaz de usuario inicial y también se cargue
ya que el framework solo puede cargar un archivo de diseño completo en una
escena.
El diseño de la primera escena se define de la siguiente manera:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/scene_container" android:layout_width="match_parent" android:layout_height="match_parent" ></androidx.constraintlayout.widget.ConstraintLayout>
El diseño de la segunda escena contiene los mismos dos campos de texto, con el los mismos IDs, en un orden diferente. Se define de la siguiente manera:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/scene_container" android:layout_width="match_parent" android:layout_height="match_parent" ></androidx.constraintlayout.widget.ConstraintLayout>
Genera escenas a partir de diseños
Luego de crear definiciones para los dos diseños de restricciones, puedes obtener un una escena para cada uno de ellos. Esto te permite hacer la transición entre las dos IU parámetros de configuración. Para obtener una escena, necesitas una referencia a la raíz de la escena y al diseño el ID del recurso.
En el siguiente fragmento de código, se muestra cómo obtener una referencia al elemento raíz de la escena y
Crea dos objetos Scene
a partir de los archivos de diseño:
Kotlin
val sceneRoot: ViewGroup = findViewById(R.id.scene_root) val aScene: Scene = Scene.getSceneForLayout(sceneRoot, R.layout.a_scene, this) val anotherScene: Scene = Scene.getSceneForLayout(sceneRoot, R.layout.another_scene, this)
Java
Scene aScene; Scene anotherScene; // Create the scene root for the scenes in this app. sceneRoot = (ViewGroup) findViewById(R.id.scene_root); // Create the scenes. aScene = Scene.getSceneForLayout(sceneRoot, R.layout.a_scene, this); anotherScene = Scene.getSceneForLayout(sceneRoot, R.layout.another_scene, this);
En la app, ahora hay dos objetos Scene
basados en la vista
jerárquicas. Ambas escenas usan el elemento raíz de escena definido por el
Elemento FrameLayout
en res/layout/activity_main.xml
.
Cómo crear una escena en tu código
También puedes crear una instancia de Scene
en tu código desde un
ViewGroup
. Usa esta técnica cuando modifiques las jerarquías de vistas.
directamente en tu código o cuando los generas de forma dinámica.
Para crear una escena a partir de una jerarquía de vistas en tu código, usa el elemento
Scene(sceneRoot, viewHierarchy)
. Llamar a este constructor es equivalente a llamar al
Scene.getSceneForLayout()
cuando ya aumentaste un archivo de diseño.
En el siguiente fragmento de código, se muestra cómo crear un Scene
del elemento raíz de la escena y la jerarquía de vistas de la escena
tu código:
Kotlin
val sceneRoot = someLayoutElement as ViewGroup val viewHierarchy = someOtherLayoutElement as ViewGroup val scene: Scene = Scene(sceneRoot, viewHierarchy)
Java
Scene mScene; // Obtain the scene root element. sceneRoot = (ViewGroup) someLayoutElement; // Obtain the view hierarchy to add as a child of // the scene root when this scene is entered. viewHierarchy = (ViewGroup) someOtherLayoutElement; // Create a scene. mScene = new Scene(sceneRoot, mViewHierarchy);
Crea acciones de escena
El framework te permite definir las acciones de escena personalizadas que ejecuta el sistema cuando entrar a una escena o salir de ella. En muchos casos, definir acciones de escena personalizadas es innecesario, ya que el framework anima el cambio entre escenas automáticamente.
Las acciones de escena son útiles para manejar los siguientes casos:
- Para animar vistas que no estén en la misma jerarquía Puedes animar vistas para las escenas inicial y final con acciones de escena de salida y entrada.
- Para animar vistas que el framework de transiciones no pueda animar automáticamente,
como objetos
ListView
. Para ver más consulta la sección sobre limitaciones.
Para proporcionar acciones de escena personalizadas, define tus acciones como
objetos Runnable
y pásalos a la
Scene.setExitAction()
o Scene.setEnterAction()
funciones. El framework llama a la función setExitAction()
en el inicio
antes de ejecutar la animación de transición y la función setEnterAction()
en la escena final después de ejecutar la animación de transición.
Cómo aplicar una transición
El framework de transición representa el estilo de animación entre escenas con una
Transition
. Puedes crear una instancia de Transition
con
subclases, como
AutoTransition
y
Fade
o
define tu propia transición.
Luego, puedes ejecutar
animación entre escenas pasando el final Scene
y el Transition
en
TransitionManager.go()
El ciclo de vida de la transición es similar al ciclo de vida de la actividad y representa la transición establece que el framework supervisa entre el inicio y el la finalización de una animación. En los estados importantes del ciclo de vida, el framework invoca a funciones de devolución de llamada que puedes implementar para ajustar tu interfaz de usuario en distintas fases de la transición.
Crea una transición
En la sección anterior, se muestra cómo crear escenas que representen el estado de
diferentes jerarquías de vistas. Una vez que defines las escenas
inicial y final,
entre los que quieras cambiar, crea un objeto Transition
que defina una animación.
El framework te permite especificar una transición integrada en un archivo de recursos
y aumentarla en tu código o crear una instancia de una transición integrada
directamente en tu código.
Clase | Etiqueta | Efecto |
---|---|---|
AutoTransition |
<autoTransition/> |
Transición predeterminada. Aplica fundido de salida, movimiento, cambio de tamaño y atenuación de entrada en las vistas, en ese orden. |
ChangeBounds |
<changeBounds/> |
Mueve las vistas y cambia su tamaño. |
ChangeClipBounds |
<changeClipBounds/> |
Captura el View.getClipBounds() antes y después de la escena.
y los anima durante la transición. |
ChangeImageTransform |
<changeImageTransform/> |
Captura la matriz de una ImageView antes y después de la escena.
y lo anima durante la transición. |
ChangeScroll |
<changeScroll/> |
Captura las propiedades de desplazamiento de los objetivos antes y después de la escena. y anima cualquier cambio. |
ChangeTransform |
<changeTransform/> |
Captura la escala y la rotación de las vistas antes y después del cambio de escena y anima esos cambios durante la transición. |
Explode |
<explode/> |
Realiza un seguimiento de los cambios en la visibilidad de las vistas de destino al comienzo y al final escenas y mueve vistas hacia adentro o hacia afuera de los bordes de la escena. |
Fade |
<fade/> |
fade_in aplica fundido de entrada en las vistas.fade_out aplica fundido de salida en las vistas.fade_in_out (predeterminado) hace un fade_out seguido de
un objeto fade_in .
|
Slide |
<slide/> |
Realiza un seguimiento de los cambios en la visibilidad de las vistas de destino al comienzo y al final escenas y mueve vistas hacia adentro o hacia afuera de uno de los bordes de la escena. |
Cómo crear una instancia de transición desde un archivo de recursos
Esta técnica te permite modificar tu definición de transición sin cambiar la el código de tu actividad. Esta técnica también es útil para separar conjuntos de datos de transición del código de la aplicación, como se muestra en la sobre la especificación de varias transiciones
Para especificar una transición integrada en un archivo de recursos, sigue estos pasos:
- Agrega el directorio
res/transition/
al proyecto. - Crea un archivo de recursos XML nuevo dentro del directorio.
- Agrega un nodo XML para una de las transiciones integradas.
Por ejemplo, el siguiente archivo de recursos especifica la transición Fade
:
<fade xmlns:android="http://schemas.android.com/apk/res/android" />
En el siguiente fragmento de código, se muestra cómo aumentar una instancia de Transition
dentro
tu actividad desde un archivo de recursos:
Kotlin
var fadeTransition: Transition = TransitionInflater.from(this) .inflateTransition(R.transition.fade_transition)
Java
Transition fadeTransition = TransitionInflater.from(this). inflateTransition(R.transition.fade_transition);
Crea una instancia de transición en tu código
Esta técnica es útil para crear objetos de transición dinámicamente si la interfaz de usuario en tu código y crear una transición simple e integrada instancias con pocos parámetros o ninguno.
Para crear una instancia de una transición integrada, invoca uno de los
constructores en las subclases de la clase Transition
. Por ejemplo, el
El siguiente fragmento de código crea una instancia de la transición Fade
:
Kotlin
var fadeTransition: Transition = Fade()
Java
Transition fadeTransition = new Fade();
Cómo aplicar una transición
Por lo general, se aplica una transición para cambiar entre diferentes jerarquías de vistas en respuesta a un evento, como una acción del usuario. Por ejemplo, considera una app de búsqueda: Cuando el usuario ingresa un término de búsqueda y presiona el botón de búsqueda, la app cambia a una escena que representa el diseño de los resultados mientras se aplica una transición que hace que se atenúe el botón de búsqueda y los resultados de la búsqueda.
Para hacer un cambio de escena mientras se aplica una transición en respuesta a un evento en
tu actividad, llama a la función de clase TransitionManager.go()
con el final
y la instancia de transición para usar en la animación, como se muestra en el
siguiente fragmento:
Kotlin
TransitionManager.go(endingScene, fadeTransition)
Java
TransitionManager.go(endingScene, fadeTransition);
El framework cambia la jerarquía de vistas dentro del elemento raíz de la escena con la vista jerarquía de la escena final mientras se ejecuta la animación especificada por el instancia de transición. La escena inicial es la escena final de los últimos transición. Si no hay una transición previa, se determina la escena inicial. automáticamente a partir del estado actual de la interfaz de usuario.
Si no especificas una instancia de transición, el administrador de transiciones
una transición automática que haga
algo razonable para la mayoría de las situaciones. Para
más información, consulta la referencia de la API para el
TransitionManager
.
Cómo elegir vistas de objetivo específicas
El framework aplica transiciones a todas las vistas en las escenas inicial y final
de forma predeterminada. En algunos casos, quizás solo quieras aplicar una animación a un subconjunto
de vistas en una escena. El marco de trabajo te permite seleccionar las vistas específicas que quieras
animar. Por ejemplo, el framework no admite la animación de cambios en
ListView
, así que no intentes animarlos durante una transición.
Cada vista que anima la transición se llama objetivo. Solo puedes seleccionar destinos que forman parte de la jerarquía de vistas asociada con una escena.
Para eliminar una o más vistas de la lista de orientaciones, llama al
removeTarget()
método antes de iniciar la transición. Para agregar solo las vistas que especifiques a la
de objetivos, llama al
addTarget()
. Para obtener más información, consulta la referencia de la API para
Transition
.
Cómo especificar varias transiciones
Para obtener el máximo impacto de una animación, hazla coincidir con el tipo de cambios que entre escenas. Por ejemplo, si quitas algunas vistas y agregas entre escenas, una animación de atenuación de salida o entrada proporciona una que indica que algunas vistas ya no están disponibles. Si mueves las vistas a diferentes puntos de la pantalla, es mejor animar el movimiento para que los usuarios notan la nueva ubicación de las vistas.
No tienes que elegir solo una animación, ya que el framework de transiciones te permite combinar efectos de animación en un conjunto de transiciones que contiene un grupo de para tus transiciones individuales integradas o personalizadas.
Para definir un conjunto de transiciones a partir de una colección de transiciones en XML, crea un
archivo de recursos en el directorio res/transitions/
y enumerar las transiciones en
el elemento TransitionSet
. Por ejemplo, el siguiente fragmento muestra cómo
especifica un conjunto de transiciones que tenga el mismo comportamiento que AutoTransition
clase:
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android" android:transitionOrdering="sequential"> <fade android:fadingMode="fade_out" /> <changeBounds /> <fade android:fadingMode="fade_in" /> </transitionSet>
Para aumentar la transición, establece un
Objeto TransitionSet
en
tu código, llama al
TransitionInflater.from()
función en tu actividad. La clase TransitionSet
se extiende desde
Transition
para que puedas usarla con un administrador de transiciones como cualquier otro
otra instancia de Transition
.
Cómo aplicar una transición sin escenas
Cambiar las jerarquías de vistas no es la única forma de modificar la interfaz de usuario. Tú también puede realizar cambios agregando, modificando y quitando vistas secundarias dentro del en la jerarquía actual.
Por ejemplo, puedes implementar una interacción de búsqueda con
un solo diseño. Comienza con un diseño que muestre un campo de búsqueda y una búsqueda.
ícono. Para cambiar la interfaz de usuario y mostrar los resultados, quita el botón de búsqueda
cuando el usuario lo presiona llamando al
ViewGroup.removeView()
y agrega los resultados de búsqueda llamando
ViewGroup.addView()
.
Puedes usar este enfoque si la alternativa es tener dos jerarquías son casi idénticos. En lugar de crear y mantener dos archivos de diseño separados para una diferencia menor en la interfaz de usuario, puedes tener un archivo de diseño con una jerarquía de vistas que se modifica en el código.
Si realizas cambios en la jerarquía de vistas actual de esta manera, no necesitas crear una escena. En cambio, puedes crear y aplicar una transición entre dos estados de una jerarquía de vistas con una transición demorada. Esta función del el framework de transiciones comienza con el estado actual de la jerarquía de vistas, los registros cambios que realices a sus vistas y aplica una transición que anima las cambia cuando el sistema vuelve a dibujar la interfaz de usuario.
Para crear una transición retrasada dentro de una jerarquía de vistas única, sigue estos pasos:
- Cuando ocurra el evento que desencadena la transición, llama al
TransitionManager.beginDelayedTransition()
y proporciona la vista superior de todas las vistas. que quieres cambiar y la transición a usar. El framework almacena la configuración el estado de las vistas secundarias y los valores de sus propiedades. - Haz cambios en las vistas secundarias según lo requiera su caso práctico. El marco de trabajo registra los cambios que realizas en las vistas secundarias y sus propiedades.
- Cuando el sistema vuelva a dibujar la interfaz de usuario según sus cambios, el el framework anima los cambios entre el estado original y el nuevo.
En el siguiente ejemplo, se muestra cómo animar la adición de una vista de texto a una vista en la jerarquía con una transición retrasada. El primer fragmento muestra el diseño archivo de definición:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/mainLayout" android:layout_width="match_parent" android:layout_height="match_parent" > <EditText android:id="@+id/inputText" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" /> ... </androidx.constraintlayout.widget.ConstraintLayout>
En el siguiente fragmento, se muestra el código que anima la adición de la vista de texto:
Kotlin
setContentView(R.layout.activity_main) val labelText = TextView(this).apply { text = "Label" id = R.id.text } val rootView: ViewGroup = findViewById(R.id.mainLayout) val mFade: Fade = Fade(Fade.IN) TransitionManager.beginDelayedTransition(rootView, mFade) rootView.addView(labelText)
Java
private TextView labelText; private Fade mFade; private ViewGroup rootView; ... // Load the layout. setContentView(R.layout.activity_main); ... // Create a new TextView and set some View properties. labelText = new TextView(this); labelText.setText("Label"); labelText.setId(R.id.text); // Get the root view and create a transition. rootView = (ViewGroup) findViewById(R.id.mainLayout); mFade = new Fade(Fade.IN); // Start recording changes to the view hierarchy. TransitionManager.beginDelayedTransition(rootView, mFade); // Add the new TextView to the view hierarchy. rootView.addView(labelText); // When the system redraws the screen to show this update, // the framework animates the addition as a fade in.
Define devoluciones de llamada del ciclo de vida de la transición
El ciclo de vida de la transición es similar al de la actividad. Representa el
indica que el framework supervisa durante el período entre una llamada
a la función TransitionManager.go()
y la finalización de
la animación. En los estados importantes del ciclo de vida, el framework invoca las devoluciones de llamada
definido por el TransitionListener
interfaz de usuario.
Las devoluciones de llamada del ciclo de vida de la transición son útiles, por ejemplo, para copiar una vista
valor de la propiedad desde la jerarquía de vista inicial hasta la jerarquía de vista final
durante un cambio de escena. No puedes simplemente copiar el valor de su vista inicial a
la vista en la jerarquía de vista final, ya que esta no es
hasta que se complete la transición. En cambio, debes almacenar el valor
en una variable y, luego, copiarla en la jerarquía de vista final cuando el framework
haya terminado la transición. Para recibir una notificación cuando se complete la transición,
implementar la
TransitionListener.onTransitionEnd()
función en tu actividad.
Para obtener más información, consulta la referencia de la API para
TransitionListener
.
Limitaciones
En esta sección, se enumeran algunas limitaciones conocidas del framework de transiciones:
- Las animaciones aplicadas a un
Es posible que
SurfaceView
no aparezca. correctamente. Las instancias deSurfaceView
se actualizan desde un subproceso que no es de IU. las actualizaciones podrían no estar sincronizadas con las animaciones de otras vistas. - Algunos tipos de transición específicos podrían no producir el efecto de animación deseado.
cuando se aplica a una
TextureView
. - Clases que extienden
AdapterView
, comoListView
, administran sus vistas secundarias de maneras que son incompatibles el framework de transiciones. Si intentas animar una vista basada enAdapterView
, ocurrirá lo siguiente: la pantalla del dispositivo podría dejar de responder. - Si intentas cambiar el tamaño de un objeto
TextView
con una animación, el texto aparece en una nueva ubicación antes de que se ha cambiado el tamaño. Para evitar este problema, no animes el cambio de tamaño de las vistas que contengan texto.