En tu gráfico de navegación, un destino puede ser una actividad. Si bien es una práctica recomendada tener una sola actividad en tu app, las apps suelen usar actividades diferentes para distintos componentes o pantallas dentro de una app. Los destinos de actividad pueden ser útiles en esos casos.
Compose y DSL de Kotlin
Agregar un destino de actividad a tu gráfico de navegación es, en esencia, lo mismo.
tanto en Compose como cuando uses el DSL de Kotlin con fragmentos. ya que, cuando pasas el elemento NavGraph
al componible NavHost
, usas la misma lambda createGraph()
.
Para obtener más información, consulta Fragmentos y el DSL de Kotlin.
XML
Crear un destino de actividad es similar a crear un destino de fragmento. Sin embargo, la naturaleza de un destino de actividad resulta bastante diferente.
De forma predeterminada, la biblioteca de Navigation adjunta el elemento NavController
a un diseño de Activity
, y el gráfico de navegación activo se define en el objeto Activity
activo. Si un usuario navega a un objeto 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 de actividad, 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 del objeto 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 elemento 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 elemento 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 URLs fijas para navegar a destinos. Es posible que también debas admitir URLs 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
con 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
.