在导航图中,目的地可以是 activity。虽然最佳实践是在应用中使用单个 activity,但应用通常会为应用内的不同组件或界面使用不同的 activity。在这种情况下,activity 目的地会很有用。
Compose 和 Kotlin DSL
向导航图添加 activity 目的地的方法基本相同
以及将 Kotlin DSL 与 fragment 一起使用时。这是因为,将 NavGraph
传递给 NavHost
可组合项时,您使用的是相同的 createGraph()
lambda。
如需了解详情,请参阅 Fragment 和 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
。