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
.