Cómo crear destinos

Puedes crear un destino a partir de un fragmento o una actividad existente. También puedes usar el Editor de Navigation para crear un destino nuevo o un marcador de posición y reemplazarlo con un fragmento o una actividad posteriormente.

Cómo crear un destino a partir de un fragmento o una actividad existente

En el Editor de Navigation, si tienes un tipo de destino existente que quieres agregar a tu gráfico de navegación, haz clic en New Destination y, luego, selecciona el destino correspondiente en el menú desplegable que se muestra. Ahora puedes acceder a una vista previa del destino en la vista Design junto con el XML correspondiente en la vista Text de tu gráfico de navegación.

Cómo crear un destino de fragmento nuevo

Para agregar un tipo de destino nuevo mediante el Editor de Navigation, haz lo siguiente:

  1. En el Editor de Navigation, haz clic en el ícono New Destination y, luego, en Create new destination.
  2. Crea tu fragmento en el diálogo New Android Component que se muestra. Si deseas obtener más información sobre los fragmentos, consulta la documentación correspondiente.

En el Editor de Navigation, verás que Android Studio agregó este destino al gráfico.

En la Figura 1, se muestra un ejemplo de un destino y un destino de marcador de posición.

Figura 1: Un destino y un marcador de posición

Cómo crear un destino a partir de un DialogFragment

Si tienes un DialogFragment existente, puedes usar el elemento <dialog> para agregar el diálogo a tu gráfico de navegación, como se muestra en el siguiente ejemplo:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:id="@+id/nav_graph">

...

<dialog
    android:id="@+id/my_dialog_fragment"
    android:name="androidx.navigation.myapp.MyDialogFragment">
    <argument android:name="myarg" android:defaultValue="@null" />
        <action
            android:id="@+id/myaction"
            app:destination="@+id/another_destination"/>
</dialog>

...

</navigation>

Cómo crear un destino de actividad nuevo

Crear un destino Activity es similar a crear un destino Fragment. Sin embargo, la naturaleza de un destino Activity resulta bastante diferente.

De forma predeterminada, la biblioteca de Navigation adjunta el NavController a un diseño de Activity, y el gráfico de navegación activo se define en la Activity activa. Si un usuario navega a una Activity diferente, el gráfico de navegación actual ya no estará dentro del alcance. Esto significa que un destino Activity debe considerarse un extremo dentro de un gráfico de navegación.

Para agregar un destino Activity, especifica el destino Activity con su nombre de clase completamente calificado:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigation_graph"
    app:startDestination="@id/simpleFragment">

    <activity
        android:id="@+id/sampleActivityDestination"
        android:name="com.example.android.navigation.activity.DestinationActivity"
        android:label="@string/sampleActivityTitle" />
</navigation>

Este XML es equivalente a la siguiente llamada a startActivity():

Kotlin

startActivity(Intent(context, DestinationActivity::class.java))

Java

startActivity(new Intent(context, DestinationActivity.class));

Es posible que tengas casos en los que este enfoque no resulte apropiado. Por ejemplo, tal vez no tengas una dependencia en tiempo de compilación en la clase de la actividad o prefieras el nivel de indirección que consiste en pasar por un intent implícito. El intent-filter en la entrada del manifiesto de la Activity de destino determina cómo debes estructurar el destino Activity.

Por ejemplo, considera el siguiente archivo de manifiesto:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.navigation.activity">
    <application>
        <activity android:name=".DestinationActivity">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <data
                    android:host="example.com"
                    android:scheme="https" />
                <category android:name="android.intent.category.BROWSABLE" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>
</manifest>

El destino Activity correspondiente debe configurarse con los atributos action y data que coincidan con aquellos en la entrada del manifiesto:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigation_graph"
    app:startDestination="@id/simpleFragment">
    <activity
        android:id="@+id/localDestinationActivity"
        android:label="@string/localActivityTitle"
        app:action="android.intent.action.VIEW"
        app:data="https://example.com"
        app:targetPackage="${applicationId}" />
</navigation>

Si especificas targetPackage en el applicationId actual, se limitará el alcance a la aplicación actual, que incluye la app principal.

El mismo mecanismo se puede usar para los casos en los que desees que una app específica sea el destino. En el siguiente ejemplo, se define como destino una app con un applicationId de com.example.android.another.app.

<?xml version="1.0" encoding="utf-8"?>`
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigation_graph"
    app:startDestination="@id/simpleFragment">
    <activity
        android:id="@+id/localDestinationActivity"
        android:label="@string/localActivityTitle"
        app:action="android.intent.action.VIEW"
        app:data="https://example.com"
        app:targetPackage="com.example.android.another.app" />
</navigation>

Argumentos dinámicos

En los ejemplos anteriores, se usaron URL fijas a fin de navegar a destinos. Es posible que también debas admitir URL dinámicas en las que se envíe información adicional como parte de la URL. Por ejemplo, puedes enviar un ID del usuario en una URL con un formato similar a https://example.com?userId=<actual user ID>.

En este caso, en lugar del atributo data, usa dataPattern. Luego, puedes proporcionar argumentos que se reemplacen por marcadores de posición con nombre dentro del valor de dataPattern:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigation_graph"
    app:startDestination="@id/simpleFragment">
    <activity
        android:id="@+id/localDestinationActivity"
        android:label="@string/localActivityTitle"
        app:action="android.intent.action.VIEW"
        app:dataPattern="https://example.com?userId={userId}"
        app:targetPackage="com.example.android.another.app">
        <argument
            android:name="userId"
            app:argType="string" />
    </activity>
</navigation>

En este ejemplo, puedes especificar un valor de userId mediante Safe Args o con un Bundle:

Kotlin

navController.navigate(
    R.id.localDestinationActivity,
    bundleOf("userId" to "someUser")
)

Java

Bundle args = new Bundle();
args.putString("userId", "someUser");
navController.navigate(R.id.localDestinationActivity, args);

En este ejemplo, se sustituye someUser por {userId} y se crea un valor de URI de https://example.com?userId=someUser.

Destinos del marcador de posición

Puedes usar marcadores de posición para representar destinos sin implementar. Un marcador de posición sirve como representación visual de un destino. Dentro del Editor de Navigation, puedes usar marcadores de posición del mismo modo que lo harías con cualquier otro destino.