Activity 目标

在您的导航图中,目标可以是一个 activity。虽然在您的应用中拥有单个 activity 是最佳实践,但应用通常会为应用中的不同组件或屏幕使用单独的 activity。在这些情况下,Activity 目标会很有用。

Compose 和 Kotlin DSL

在 Compose 和将 Kotlin DSL 与 fragment 结合使用时,向导航图添加 activity 目标基本相同。这是因为当您将 NavGraph 传递给 NavHost 可组合项时,您使用的是相同的 createGraph() lambda。

如需了解更多信息,请参阅Fragment 和 Kotlin DSL

XML

创建 activity 目标类似于创建 fragment 目标。然而,activity 目标的性质却大不相同。

默认情况下,导航库会将 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>

相应的 Activity 目标需要配置 actiondata 属性,这些属性与清单条目中的属性匹配

<?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 会将作用域限制为当前应用,其中包括主应用。

相同的机制可用于您希望特定应用作为目标的情况。以下示例将目标定义为 applicationIdcom.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 的一部分发送。例如,您可以在 URL 中发送用户 ID,格式类似于 https://example.com?userId=<actual user 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 ArgsBundle 来指定 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