Destinazioni attività

Nel grafico di navigazione, una destinazione può essere un'attività. Sebbene sia una best practice avere una singola attività nell'app, le app spesso usano attività separate per componenti o schermate all'interno di un'app. Le destinazioni delle attività possono essere utili in questi casi.

Compose e Kotlin DSL

L'aggiunta di una destinazione di attività al grafico di navigazione è sostanzialmente la stessa sia in Compose sia quando si utilizza il Kotlin DSL con frammenti. Il motivo è che quando passi NavGraph al tuo NavHost componibile, utilizzi la stessa lambda createGraph().

Per ulteriori informazioni, consulta Creare un grafico in modo programmatico utilizzando la DSL di Kotlin.

XML

La creazione di una destinazione per l'attività è simile a quella di una destinazione frammento. Tuttavia, la natura della destinazione di un'attività è piuttosto diversa.

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

Per aggiungere la destinazione di un'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 riscontrare casi in cui questo approccio non è appropriato. Ad esempio, potresti non avere una dipendenza in fase di compilazione dalla classe di attività oppure potresti preferire il livello indiretto di passare attraverso un intent implicito. Il intent-filter nella voce manifest per la destinazione Activity determina come devi strutturare la 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 presenti nella voce 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 con l'attuale applicationId, l'ambito verrà limitato all'applicazione corrente, che include l'app principale.

Lo stesso meccanismo può essere utilizzato nei casi in cui vuoi che un'app specifica 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 gli URL fissi per raggiungere le destinazioni. Potresti anche dover supportare gli 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, invece dell'attributo data, utilizza dataPattern. Puoi quindi fornire argomenti da sostituire per i 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 Args sicuri 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 pari a https://example.com?userId=someUser.