W grafie nawigacji miejscem docelowym może być działanie. Chociaż najlepszym rozwiązaniem jest używanie w aplikacji tylko jednego działania, często aplikacje używają osobnych działań w przypadku różnych komponentów lub ekranów. W takich przypadkach miejsca docelowe działania mogą być przydatne.
Compose i Kotlin DSL
Dodawanie miejsca docelowego działania do grafu nawigacji jest zasadniczo takie samo w Compose i w przypadku używania Kotlin DSL z fragmentami. Dzieje się tak, ponieważ podczas przekazywania NavGraph do elementu kompozycyjnego NavHost używasz tej samej lambdy createGraph().
Więcej informacji znajdziesz w artykule Fragmenty i Kotlin DSL.
XML
Tworzenie miejsca docelowego działania jest podobne do tworzenia miejsca docelowego fragmentu. Natura miejsca docelowego działania jest jednak zupełnie inna.
Domyślnie biblioteka Navigation dołącza NavController do układu
Activity, a aktywny graf nawigacji jest ograniczony do aktywnego
Activity. Jeśli użytkownik przejdzie do innego Activity, bieżący graf nawigacji nie będzie już w zakresie. Oznacza to, że miejsce docelowe Activity należy traktować jako punkt końcowy w grafie nawigacji.
Aby dodać miejsce docelowe działania, określ docelowe Activity za pomocą jego pełnej i jednoznacznej nazwy klasy:
<?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>
Ten kod XML jest odpowiednikiem tego wywołania startActivity():
Kotlin
startActivity(Intent(context, DestinationActivity::class.java))
Java
startActivity(new Intent(context, DestinationActivity.class));
Mogą wystąpić przypadki, w których to podejście nie będzie odpowiednie. Na przykład możesz nie mieć zależności od klasy Activity w czasie kompilowania lub możesz preferować poziom pośrednictwa związany z użyciem intencji ogólnej.
intent-filter w wpisie manifestu dla docelowego Activity
określa, jak należy skonstruować miejsce docelowe Activity.
Rozważmy na przykład ten plik manifestu:
<?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>
Odpowiednie miejsce docelowe Activity musi być skonfigurowane za pomocą
action i data atrybutów pasujących do tych w wpisie manifestu:
<?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>
Określenie targetPackage jako bieżącego applicationId ogranicza zakres do bieżącej aplikacji, która obejmuje aplikację główną.
Tego samego mechanizmu można użyć w przypadkach, gdy chcesz, aby miejscem docelowym była konkretna aplikacja. Ten przykład definiuje miejsce docelowe jako aplikację z applicationId o wartości 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>
Argumenty dynamiczne
W poprzednich przykładach do przechodzenia do miejsc docelowych używano stałych adresów URL. Może być też konieczne obsługiwanie dynamicznych adresów URL, w których dodatkowe informacje są wysyłane jako część adresu URL. Możesz na przykład wysłać identyfikator użytkownika w adresie URL w formacie podobnym do
https://example.com?userId=<actual user ID>.
W takim przypadku zamiast atrybutu data użyj atrybutu dataPattern.
Możesz wtedy podać argumenty, które mają zostać zastąpione nazwanymi zmiennymi w wartości 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>
W tym przykładzie możesz określić wartość userId za pomocą Safe Args
lub 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);
W tym przykładzie wartość {userId} zostanie zastąpiona wartością someUser, a wartość URI będzie mieć postać
https://example.com?userId=someUser.