活动目标

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

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 目标需要使用与清单条目中相同的 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 的一部分发送。例如,您可以在格式类似于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 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