Cómo iniciar 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 explode, las vistas entran en la 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 explode, 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 sin problemas entre estas actividades.

Android admite las siguientes transiciones de entrada y salida:

  • explode: Mueve las vistas hacia adentro o hacia afuera del centro de la escena.
  • slide: Mueve vistas hacia adentro o hacia afuera de uno de los bordes de la escena.
  • fade: 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 de 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 las 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 muestra 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 el sistema version en tiempo de ejecución antes de invocar las APIs para cualquiera de estas funciones:

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
}

Cómo especificar transiciones personalizadas

Primero, habilita las transiciones de contenido de la ventana con el atributo android:windowActivityTransitions cuando definas un estilo que herede del tema de Material. También puedes especificar transiciones de entrada, salida y elementos compartidos en tu definición de diseño:

<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 en la siguiente forma:

<!-- 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 la ventana 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_ACTIVITY_TRANSITIONS)

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

Java

// Inside your activity (if you did not enable transitions in your theme)
getWindow().requestFeature(Window.FEATURE_ACTIVITY_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 de la actividad de llamada. Las funciones setEnterTransition() y setSharedElementEnterTransition() definen la transición de entrada de la actividad llamada.

Para obtener el efecto completo de una transición, debes habilitar las transiciones de contenido de la ventana en las actividades de llamada y en las llamadas. De lo contrario, la actividad que realiza la llamada inicia la transición de salida, pero luego verás las transiciones de la ventana, como escalar o atenuar.

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 las transiciones y estableces una transición de salida para una actividad, la transición se activa cuando inicias otra actividad, de la siguiente manera:

Kotlin

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

Java

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

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

Cómo iniciar una actividad con un elemento compartido

Para realizar una animación de transición de pantalla entre dos actividades que tienen un elemento compartido, haz lo siguiente:

  1. Habilita las transiciones del contenido de las ventanas en tu tema.
  2. Especifica una transición de elementos compartidos en tu estilo.
  3. Cómo definir tu transición como un recurso XML.
  4. Asigna un nombre en 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());
    }
});

En el caso de las vistas dinámicas compartidas que generas en tu código, usa la función View.setTransitionName() para especificar un nombre de elemento común 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().

Cómo iniciar una actividad con varios 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 de la siguiente manera:

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"));