对话框目标

在 Android 导航中,术语“对话框目标”指的是应用导航图中以对话框窗口形式出现的目标,覆盖应用 UI 元素和内容。

由于对话框目标出现在填充导航宿主的托管目标之上,因此在对话框目标与您的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

如果您正在使用片段并且正在使用Kotlin DSL创建您的图,则添加对话框目的地与使用 Compose 时非常相似。

考虑以下代码段中如何也使用dialog()函数添加一个使用片段的对话框目的地

// 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>