在导航图中,目的地可以是 activity。虽然最佳实践是在应用中使用单个 activity,但应用通常会为应用内的不同组件或界面使用不同的 activity。在这种情况下,activity 目的地会很有用。
Compose 和 Kotlin DSL
向导航图添加 activity 目的地的方法基本相同
以及将 Kotlin DSL 与 fragment 一起使用时。这是因为,将 NavGraph
传递给 NavHost
可组合项时,您使用的是相同的 createGraph()
lambda。
如需了解详情,请参阅使用 Kotlin DSL 以编程方式构建图表。
XML
创建 activity 目的地类似于创建 fragment 目的地。但是,目的地的性质完全不同。
默认情况下,Navigation 库会将 NavController
附加到 Activity
布局,并且处于活跃状态的导航图的作用域限定为处于活跃状态的 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));
在某些情况下,您可能会发现此方法不适合。例如,您可能在 activity 类中未采用编译时依赖项,或者您可能会更倾向于使用运行某个隐式 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>
您需要使用与清单条目中匹配的 action
和 data
属性来配置相应的 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/localDestinationActivity" android:label="@string/localActivityTitle" app:action="android.intent.action.VIEW" app:data="https://example.com" app:targetPackage="${applicationId}" /> </navigation>
为当前 applicationId
指定 targetPackage
可将作用域限定为当前应用(其包含主应用)。
如果您希望将特定应用作为目的地,可以使用上述机制。以下示例将目的地定义成 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>
动态参数
前面的示例使用固定网址来导航到目的地。您可能还需要支持动态网址,在动态网址中,会将其他信息作为网址的一部分发送。例如,您可以在格式类似于 https://example.com?userId=<actual user ID>
的网址中发送用户 ID。
在这种情况下,请使用 dataPattern
,而不是 data
属性。然后,您可为 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
。