Destinazioni attività

Nel grafico di navigazione, una destinazione può essere un'attività. Anche se la best practice è avere una sola attività nell'app, spesso le app utilizzano attività separate per componenti o schermate distinti all'interno di un'app. Le destinazioni attività possono essere utili in questi casi.

Compose e Kotlin DSL

L'aggiunta di una destinazione di attività al grafico di navigazione è essenzialmente la stessa sia in Compose sia quando si utilizza Kotlin DSL con i fragment. Questo perché quando passi NavGraph al composable NavHost, utilizzi la stessa lambda createGraph().

Per saperne di più, consulta Frammenti e Kotlin DSL.

XML

La creazione di una destinazione attività è simile alla creazione di una destinazione frammento. Tuttavia, la natura di una destinazione di attività è piuttosto diversa.

Per impostazione predefinita, la libreria di navigazione collega NavController a un layout Activity e il grafico di navigazione attivo è limitato all'Activity attivo. Se un utente passa a un altro Activity, il grafico di navigazione corrente non è più incluso nell'ambito. Ciò significa che una destinazione Activity deve essere considerata un endpoint all'interno di un grafico di navigazione.

Per aggiungere una destinazione attività, specifica la destinazione Activity con il nome completo della classe:

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

Questo XML equivale alla seguente chiamata a startActivity():

Kotlin

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

Java

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

Potresti avere casi in cui questo approccio non è appropriato. Ad esempio, potresti non avere una dipendenza in fase di compilazione dalla classe di attività o potresti preferire il livello di indirezione di un intent implicito. Il intent-filter nella voce del manifest per la destinazione Activity determina la struttura della destinazione Activity.

Ad esempio, considera il seguente file manifest:

<?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 destinazione Activity corrispondente deve essere configurata con gli attributi action e data corrispondenti a quelli della voce del manifest:

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

Se specifichi targetPackage per l'attuale applicationId, l'ambito viene limitato all'applicazione corrente, che include l'app principale.

Lo stesso meccanismo può essere utilizzato per i casi in cui vuoi che una specifica app sia la destinazione. L'esempio seguente definisce una destinazione come un'app con un applicationId di 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>

Argomenti dinamici

Gli esempi precedenti utilizzavano URL fissi per accedere alle destinazioni. Potresti anche dover supportare URL dinamici in cui vengono inviate informazioni aggiuntive come parte dell'URL. Ad esempio, potresti inviare un ID utente in un URL con un formato simile a https://example.com?userId=<actual user ID>.

In questo caso, utilizza dataPattern anziché l'attributo data. Puoi quindi fornire argomenti da sostituire ai segnaposto denominati all'interno del valore 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>

In questo esempio, puoi specificare un valore userId utilizzando 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);

Questo esempio sostituisce someUser con {userId} e crea un valore URI di https://example.com?userId=someUser.