在 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() }
}
}
- 起始目标使用
Home
路由。由于composable()
将其添加到图中,因此它是一个托管目标。 - 另一个目标使用
Settings
路由。- 同样,由于
dialog()
将其添加到图中,因此它是一个对话框目标。 - 当用户从
HomeScreen
导航到SettingsScreen
时,后者将显示在HomeScreen
之上。
- 同样,由于
- 虽然
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>