Inicia una actividad con una animación

Las transiciones de actividades en las apps de Material Design proporcionan conexiones visuales entre diferentes estados mediante el movimiento y las transformaciones entre elementos comunes. Puedes especificar animaciones personalizadas para entrar y salir de las transiciones y para las transiciones de elementos compartidos entre actividades.

Figura 1: Una transición con elementos compartidos

  • Una transición de entrada determina cómo entran en escena las vistas en una actividad. Por ejemplo, en la transición de entrada expandir, las vistas entran en escena desde el exterior y vuelan hacia el centro de la pantalla.
  • Una transición de salida determina cómo salen de escena las vistas en una actividad. Por ejemplo, en la transición de salida expandir, las vistas salen de escena lejos del centro.
  • Una transición de elementos compartidos determina cómo las vistas que están compartidas entre dos actividades realizan la transición entre estas. Por ejemplo, si dos actividades tienen la misma imagen en diferentes posiciones y tamaños, la transición de elementos compartidos changeImageTransform traduce y escala la imagen suavemente entre estas actividades.

Android admite las siguientes transiciones de entrada y salida:

  • expandir: Desplaza vistas hacia adentro o hacia afuera del centro de la escena.
  • deslizar: Desplaza vistas hacia adentro o hacia afuera de uno de los bordes de la escena.
  • difuminar: Agrega o quita una vista de la escena cambiando su opacidad.

Toda transición que extiende la clase Visibility se admite como una transición de entrada o salida. Para obtener más información, consulta la referencia de la API para la clase Transition.

Android también admite las siguientes transiciones de elementos compartidos:

  • changeBounds: Anima los cambios en los límites del diseño de las vistas de destino.
  • changeClipBounds: Anima los cambios en los límites de recorte de las vistas de destino.
  • changeTransform: Anima los cambios en escala y rotación de las vistas de destino.
  • changeImageTransform: Anima los cambios de tamaño y escala de imágenes de destino.

Cuando habilitas las transiciones de actividades en tu app, la transición predeterminada entre difuminados se activa entre las actividades que ingresan y salen.

Figura 2: Una transición de escena con un elemento compartido

Para ver un código de ejemplo que anima entre actividades con elementos compartidos, consulta ActivitySceneTransitionBasic.

Comprueba la versión del sistema

Las API de transición de actividad están disponibles en Android 5.0 (API nivel 21) y versiones posteriores. Para conservar la compatibilidad con versiones anteriores de Android, comprueba la version del sistema en tiempo de ejecución antes de invocar las API para cualquiera de las siguientes características:

Kotlin

    // Check if we're running on Android 5.0 or higher
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        // Apply activity transition
    } else {
        // Swap without transition
    }
    

Java

    // Check if we're running on Android 5.0 or higher
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        // Apply activity transition
    } else {
        // Swap without transition
    }
    

Especifica transiciones personalizadas

Primero, habilita las transiciones de contenidos de las ventanas con el atributo android:windowActivityTransitions cuando definas un estilo que herede del tema material. También puedes especificar transiciones de entrada, salida y elementos compartidos en tu definición de estilo:

    <style name="BaseAppTheme" parent="android:Theme.Material">
      <!-- enable window content transitions -->
      <item name="android:windowActivityTransitions">true</item>

      <!-- specify enter and exit transitions -->
      <item name="android:windowEnterTransition">@transition/explode</item>
      <item name="android:windowExitTransition">@transition/explode</item>

      <!-- specify shared element transitions -->
      <item name="android:windowSharedElementEnterTransition">
        @transition/change_image_transform</item>
      <item name="android:windowSharedElementExitTransition">
        @transition/change_image_transform</item>
    </style>
    

La transición change_image_transform en este ejemplo se define de la siguiente manera:

    <!-- res/transition/change_image_transform.xml -->
    <!-- (see also Shared Transitions below) -->
    <transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
      <changeImageTransform/>
    </transitionSet>
    

El elemento changeImageTransform corresponde a la clase ChangeImageTransform. Para obtener más información, consulta la referencia de la API de Transition.

Para habilitar las transiciones del contenido de las ventanas en tu código, llama a la función Window.requestFeature():

Kotlin

    // inside your activity (if you did not enable transitions in your theme)
    with(window) {
        requestFeature(Window.FEATURE_CONTENT_TRANSITIONS)

        // set an exit transition
        exitTransition = Explode()
    }
    

Java

    // inside your activity (if you did not enable transitions in your theme)
    getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

    // set an exit transition
    getWindow().setExitTransition(new Explode());
    

Para especificar transiciones en tu código, llama a estas funciones con un objeto Transition:

Las funciones setExitTransition() y setSharedElementExitTransition() definen la transición de salida para la actividad de llamada. Las funciones setEnterTransition() y setSharedElementEnterTransition() definen la transición de entrada para la actividad llamada.

Para obtener el efecto completo de una transición, debes habilitar las transiciones del contenido de las ventanas tanto para las actividades que realizan la llamada como para aquellas que son invocadas. De lo contrario, la actividad que realiza la llamada comenzará la transición de salida, pero luego observarás una transición de ventanas (como escalar o difuminar).

Para iniciar una transición de entrada lo antes posible, usa la función Window.setAllowEnterTransitionOverlap() en la actividad llamada. Esto te permite tener transiciones de entrada más intensas.

Inicia una actividad mediante transiciones

Si habilitas transiciones y estableces una transición de salida para una actividad, la transición se activa cuando inicias otra actividad, como alguna de las siguientes:

Kotlin

    startActivity(intent,
                  ActivityOptions.makeSceneTransitionAnimation(this).toBundle())
    

Java

    startActivity(intent,
                  ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
    

Si estableciste una transición de entrada para la segunda actividad, la transición también se activa cuando se inicia la actividad. Para inhabilitar las transiciones cuando inicias otra actividad, proporciona un conjunto de opciones null.

Inicia una actividad con un elemento compartido

Para realizar una animación de transiciones de pantallas entre dos actividades que tienen un elemento compartido:

  1. Habilita las transiciones del contenido de las ventanas en tu tema.
  2. Especifica una transición de elementos compartidos en tu estilo.
  3. Define tu transición como un recurso XML.
  4. Asigna un nombre común para los elementos compartidos en ambos diseños con el atributo android:transitionName.
  5. Usa la función ActivityOptions.makeSceneTransitionAnimation().

Kotlin

    // get the element that receives the click event
    val imgContainerView = findViewById<View>(R.id.img_container)

    // get the common element for the transition in this activity
    val androidRobotView = findViewById<View>(R.id.image_small)

    // define a click listener
    imgContainerView.setOnClickListener( {
        val intent = Intent(this, Activity2::class.java)
        // create the transition animation - the images in the layouts
        // of both activities are defined with android:transitionName="robot"
        val options = ActivityOptions
                .makeSceneTransitionAnimation(this, androidRobotView, "robot")
        // start the new activity
        startActivity(intent, options.toBundle())
    })
    

Java

    // get the element that receives the click event
    final View imgContainerView = findViewById(R.id.img_container);

    // get the common element for the transition in this activity
    final View androidRobotView = findViewById(R.id.image_small);

    // define a click listener
    imgContainerView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(this, Activity2.class);
            // create the transition animation - the images in the layouts
            // of both activities are defined with android:transitionName="robot"
            ActivityOptions options = ActivityOptions
                .makeSceneTransitionAnimation(this, androidRobotView, "robot");
            // start the new activity
            startActivity(intent, options.toBundle());
        }
    });
    

Para las vistas dinámicas compartidas que generas en tu código, usa la función View.setTransitionName() a fin de especificar un nombre común de elemento en ambas actividades.

Para invertir la animación de transición de escenas cuando terminas la segunda actividad, llama a la función Activity.finishAfterTransition() en lugar de a Activity.finish().

Inicia una actividad con múltiples elementos compartidos

Para realizar una animación de transición de escenas entre dos actividades que tienen más de un elemento compartido, define los elementos compartidos en ambos diseños con el atributo android:transitionName (o usa la función View.setTransitionName() en ambas actividades) y crea un objeto ActivityOptions como se indica a continuación:

Kotlin

    // Rename the Pair class from the Android framework to avoid a name clash
    import android.util.Pair as UtilPair
    ...
    val options = ActivityOptions.makeSceneTransitionAnimation(this,
            UtilPair.create(view1, "agreedName1"),
            UtilPair.create(view2, "agreedName2"))
    

Java

    ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
            Pair.create(view1, "agreedName1"),
            Pair.create(view2, "agreedName2"));