在您的导航图中,目标可以是活动。虽然在您的应用中只有一个活动是最佳实践,但应用通常会为应用内的不同组件或屏幕使用单独的活动。在这种情况下,活动目标可能很有用。
Compose 和 Kotlin DSL
在 Compose 中以及在使用 Kotlin DSL 与片段时,向导航图添加活动目标基本上是相同的。这是因为当将您的 NavGraph
传递到您的 NavHost
可组合项时,您使用的是相同的 createGraph()
lambda。
有关更多信息,请参阅 片段和 Kotlin DSL。
XML
创建 活动 目标类似于创建 片段 目标。但是,活动目标的性质却大不相同。
默认情况下,导航库 将 NavController
附加到 Activity
布局,并且活动导航图的作用域限定为活动 Activity
。如果用户导航到不同的 Activity
,则当前导航图将不再处于作用域内。这意味着应将 Activity
目标视为导航图中的端点。
要添加活动目标,请使用其完全限定类名指定目标 Activity
<?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>
此 XML 等效于对 startActivity()
的以下调用
Kotlin
startActivity(Intent(context, DestinationActivity::class.java))
Java
startActivity(new Intent(context, DestinationActivity.class));
在某些情况下,这种方法可能不适用。例如,您可能没有对活动类的编译时依赖项,或者您可能更喜欢通过隐式 Intent 进行间接操作。目标 Activity
的清单条目中的 intent-filter
指示您需要如何构建 Activity
目标。
例如,考虑以下清单文件
<?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>
相应的 Activity
目标需要使用与清单条目中相同的 action
和 data
属性进行配置
<?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>
将 targetPackage
指定为当前 applicationId
将作用域限制为当前应用程序,其中包括主应用。
相同的机制可用于您希望特定应用成为目标的情况。以下示例定义了一个目标,该目标是一个具有applicationId
为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>
动态参数
前面的示例使用固定 URL 导航到目标。您可能还需要支持动态 URL,其中其他信息作为 URL 的一部分发送。例如,您可以在格式类似于https://example.com?userId=<actual user ID>
的 URL 中发送用户 ID。
在这种情况下,请勿使用data
属性,而是使用dataPattern
。然后,您可以提供参数来替换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>
在此示例中,您可以使用Safe Args或Bundle
指定userId
值。
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);
此示例将someUser
替换为{userId}
,并创建 URI 值https://example.com?userId=someUser
。