Экраны
@Serializable
sealed class Screen {
@Serializable
data object Home : Screen()
@Serializable
data class Profile(val name: String) : Screen()
}
Настроить навигацию
@Composable
fun AppNavigation(
modifier: Modifier = Modifier,
startDestination: Screen = Screen.Home,
navController: NavHostController = rememberNavController()
) {
val currentNavBackStackEntry: NavBackStackEntry? by navController.currentBackStackEntryAsState()
// Error
val currentScreen: Screen = currentNavBackStackEntry?.toRoute<Screen>() ?: Screen.Home
val navGraph = navController.createGraph(
startDestination = startDestination,
) {
composable<Screen.Home> {
HomeScreen(onNavigateToProfile = { navController.navigate(it) })
}
composable<Screen.Profile> { navBackStackEntry ->
val profile = navBackStackEntry.toRoute<Screen.Profile>()
ProfileScreen(name = profile.name)
}
}
NavHost(navController = navController, graph = navGraph, modifier = modifier)
}
Я пытаюсь получить текущий экран из набора реактивного ранца навигационного типа. Но toRoute()
используйте только с маршрутами в навигационном графе.
Пожалуйста, укажите, что вы планируете делать currentScreen
— вы пытаетесь сравнить это с чем-то другим?
@ianhanniballake Мое временное решение — сравнить строки currentNavBackStackEntry?.destination?.route
и Screen::class.qualifiedName
. Есть ли другой способ получить текущий экран типа Screen
Вы фактически не ответили на мой вопрос - где вы на самом деле используете текущий экран? Ваш код по-прежнему ничего не делает с этой информацией. Пожалуйста, включите этот код.
вам нужен вариант использования currentScreen? хм, заголовок TopAppBar, условная навигация...
«Вам нужен вариант использования для currentScreen? хм, заголовок TopAppBar, условие навигации...» — вы знаете «текущий экран» внутри вашего навигационного графа. Например, внутри лямбды composable<Screen.Home>
вы знаете, что «текущий экран» — это Screen.Home
. Там вы можете обновлять состояние по мере необходимости, чтобы влиять на изменения в элементах за пределами навигационного графика, например в некоторых заголовках в строке заголовка. Я подозреваю, что именно поэтому Ян просит вас показать код, который будет зависеть от currentScreen
— такое ощущение, что есть и другие решения.
Функция hasRoute()
может помочь вам с текущим экраном следующим образом:
val navBackStackEntry by navController.currentBackStackEntryAsState()
navBackStackEntry?.destination?.let { currentDestination ->
shouldShowAppBar = !currentDestination.hasRoute(Settings::class)
}
Не красиво, но пока работает.
@Serializable
sealed class Screen(@StringRes val title: Int, val showAppBar: Boolean = true) {
@Serializable
data object Home : Screen(R.string.app_name)
@Serializable
data object Login : Screen(R.string.app_name, showAppBar = false)
}
val backStackEntry by navController.currentBackStackEntryAsState()
val currentScreen = backStackEntry?.destination?.let {
when (it.route) {
Screen.Login::class.qualifiedName -> Screen.Login
else -> Screen.Home
}
} ?: Screen.Home
Scaffold(
topBar = {
if (currentScreen.showAppBar) {
AppBar()
}
},
)
Пожалуйста, замените свой код минимальным воспроизводимым примером, чтобы мы могли опробовать его самостоятельно. Убедитесь, что он является исполняемым и демонстрирует описанную вами проблему.