对话框目的地

在 Android 导航中,“对话框目的地”一词是指应用导航图中的目的地,会以对话框窗口的形式叠加在应用界面元素和内容之上。

由于对话框目的地显示在填充导航宿主的托管目的地之上,因此对于对话框目的地如何与 NavController 的返回堆栈交互,有一些重要注意事项。

对话框可组合项

如需在 Compose 中创建对话框目的地,请使用 dialog() 函数向 NavHost 添加目的地。该函数的行为与 composable 基本相同,只不过它会创建对话框目的地而非托管目的地

请参考以下示例:

@Serializable
object Home
@Serializable
object Settings
@Composable
fun HomeScreen(onNavigateToSettings: () -> Unit){
    Column {
        Text("Home")
        Button(onClick = onNavigateToSettings){
            Text("Open settings")
        }
    }
}

// This screen will be displayed as a dialog
@Composable
fun SettingsScreen(){
    Text("Settings")
    // ...
}

@Composable
fun MyApp() {
    val navController = rememberNavController()
    NavHost(navController, startDestination = Home) {
        composable<Home> { HomeScreen(onNavigateToSettings = { navController.navigate(route = Settings) }) }
        dialog<Settings> { SettingsScreen() }
    }
}
  1. 起始目的地使用 Home 路线。由于 composable() 会将其添加到图中,因此它是一个托管目的地。
  2. 另一个目的地使用 Settings 路由。
    • 同样,由于 dialog() 会将其添加到图中,因此它是一个对话框目的地。
    • 当用户从 HomeScreen 导航到 SettingsScreen 时,后者会显示在 HomeScreen 之上。
  3. 虽然 SettingsScreen 本身不包含 Dialog 可组合项,但由于它是对话框目的地,NavHost 会在 Dialog 中显示它。

对话框目的地会显示在 NavHost 中的上一个目的地之上。如果对话框表示应用中的单独屏幕,并且该屏幕需要自己的生命周期和已保存状态,并且独立于导航图中的任何其他目的地,请使用这些对话框。如果您想使用对话框显示不太复杂的提示(例如确认),不妨考虑使用 AlertDialog 或相关可组合项。

Kotlin DSL

如果您使用 fragment,同时还使用 Kotlin DSL 创建图,添加对话框目的地与使用 Compose 时的操作非常相似。

思考一下,以下代码段如何亦使用 dialog() 函数来添加使用 fragment 的对话框目的地:

// Define destinations with serializable classes or objects
@Serializable
object Home
@Serializable
object Settings

// Add the graph to the NavController with `createGraph()`.
navController.graph = navController.createGraph(
    startDestination = Home
) {
    // Associate the home route with the HomeFragment.
    fragment<HomeFragment, Home> {
        label = "Home"
    }

    // Define the settings destination as a dialog using DialogFragment.
    dialog<SettingsFragment, Settings> {
        label = "Settings"
    }
}

XML

如果您已有 DialogFragment,请使用 <dialog> 元素将此对话框添加到导航图,如以下示例所示:

<?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/nav_graph">

...

<dialog
    android:id="@+id/my_dialog_fragment"
    android:name="androidx.navigation.myapp.MyDialogFragment">
    <argument android:name="myarg" android:defaultValue="@null" />
        <action
            android:id="@+id/myaction"
            app:destination="@+id/another_destination"/>
</dialog>

...

</navigation>