Destinations d'activité

Dans votre graphique de navigation, une destination peut être une activité. Bien qu'il soit recommandé d'avoir une seule activité dans votre appli, les applis utilisent souvent des activités distinctes pour les composants et les écrans distincts d'une appli. Les destinations d'activité peuvent être utiles dans ce cas.

Compose et DSL Kotlin

L'ajout d'une destination d'activité à votre graphique de navigation est essentiellement le même dans Compose et lors de l'utilisation du DSL Kotlin avec des fragments. En effet, lorsque vous transmettez votre NavGraph à votre composable NavHost, vous utilisez le même lambda createGraph().

Pour en savoir plus, consultez Fragments et langage DSL Kotlin.

XML

La création d'une destination d'activité est semblable à la création d'une destination de fragment. Cependant, la nature d'une destination d'activité est assez différente.

Par défaut, la bibliothèque Navigation associe le NavController à une mise en page d'Activity, et le graphique de navigation active est limité à l'Activity active. Si un utilisateur accède à une autre Activity, le graphique de navigation actuel n'est plus inclus dans le champ d'application. Cela signifie qu'une destination Activity doit être considérée comme un point de terminaison dans un graphique de navigation.

Pour ajouter une destination d'activité, précisez la destination Activity avec son nom de classe complet :

<?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>

Ce fichier XML équivaut à l'appel suivant de startActivity() :

Kotlin

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

Java

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

Dans certains cas, cette approche n'est pas adaptée. Par exemple, vous ne disposez peut-être pas d'une dépendance en temps de compilation sur la classe d'activité ou vous préférez le niveau d'indirection d'un intent implicite. L'élément intent-filter dans l'entrée du fichier manifeste de destination Activity indique la façon dont vous devez structurer la destination Activity.

Prenons l'exemple du fichier manifeste suivant :

<?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>

La destination Activity correspondante doit être configurée avec les attributs action et data correspondant à ceux de l'entrée du fichier manifeste :

<?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 vous définissez targetPackage avec la valeur applicationId actuelle, vous limitez la portée à l'application actuelle, qui inclut l'application principale.

Le même mécanisme peut être utilisé si vous souhaitez qu'une application spécifique devienne la destination. L'exemple suivant définit une destination comme une application avec un applicationId défini sur 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>

Arguments dynamiques

Les exemples précédents utilisaient des URL fixes pour accéder aux destinations. Vous devrez peut-être également accepter les URL dynamiques, qui incluent des informations supplémentaires. Par exemple, vous pouvez envoyer un ID utilisateur dans une URL dans un format semblable à https://example.com?userId=<actual user ID>.

Dans ce cas, utilisez dataPattern à la place de l'attribut data. Vous pouvez ensuite fournir des arguments à remplacer pour les espaces réservés nommés dans la valeur 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>

Dans cet exemple, vous pouvez définir une valeur userId à l'aide de Safe Args ou d'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);

Cet exemple remplace someUser par {userId} et crée la valeur d'URI https://example.com?userId=someUser.