Как обрабатывать обратную навигацию с помощью Jetpack Compose + Navigation (без фрагментов)
Я пытаюсь перейти, скажем, от онбординга к дашборду и дальше, и выскакиваю из онбординга, как только пользователь попадает на дашборд, но все еще с «обратным действием» я снова попадаю в онбординг.
Вот пример кода:
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MainUI()
}
}
}
@Composable
fun MainUI() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = "onboarding"
) {
composable("onboarding") {
Column {
Text("I am on onboarding")
Button(onClick = {
navController.navigate("dashboard") {
popUpTo("dashboard") // I want to get rid of onboarding here
}
}) {
Text("go to dashboard")
}
}
}
composable("dashboard") {
Column {
Text("I am on dashboard")
Button(onClick = {
navController.navigate("detail")
}) {
Text("go to detail")
}
}
}
composable("detail") {
Text("I am on detail")
}
}
}
Это тоже не работает
navController.navigate("dashboard") {
popUpTo("dashboard") {
inclusive = true // no difference
}
// ....
popUpTo("onboarding") // also nothing
// ....
popUpTo("onboarding") {
inclusive = true // this crashes -> NavGraph cannot be cast to ComposeNavigator$Destination
}
}
По какой-то причине этот вид работает, поэтому панель инструментов закрывается, и я попадаю в адаптацию по деталям 🤦
navController.navigate("detail") {
popUpTo("dashboard") {
inclusive = true
}
}
4 ответа
Я нашел свое решение очень простым, если я ошибаюсь, пожалуйста, просветите меня.
navController.popBackStack()
Вы можете использовать ссылку BackHandler :
@Composable
fun TestScreen() {
BackHandler {
// code
// example - activity.finish()
}
}
Как уже сказал @James Christian KaguonavController.popBackStack()
вариант. Но вы должны быть осторожны при использовании этого метода. По какой-то причине размер BackQueue составляет не менее 2, и если выталкивание обратного стека ниже этого значения, навигация больше не работает.
Поэтому я написал следующую простую функцию расширения:
fun NavController.navigateBack() {
if (backQueue.size > 2) {
popBackStack()
}
}
Что ж, я сам нашел рабочее решение, но все еще не уверен, нужен ли этот «шаблонный код» :( Но это работает как задумано, означает, что «страница» закрывается после перехода с нее.
NavHost(
navController = navController,
startDestination = "onboarding"
) {
navigation(
startDestination = "onboardingUI",
route = "onboarding"
) {
composable("onboardingUI") {
Column {
Text("I am on onboarding")
Button(onClick = {
navController.navigate("dashboard"){
popUpTo("onboarding")
}
}) {
Text("go to dashboard")
}
}
}
}
navigation(startDestination = "dashboardUI", route = "dashboard") {
composable("dashboardUI") {
Column {
Text("I am on dashboard")
Button(onClick = {
navController.navigate("detail"){
popUpTo("dashboard")
}
}) {
Text("go to detail")
}
}
}
}
navigation(startDestination = "detailUI", route = "detail") {
composable("detailUI") {
Text("I am on detail")
}
}
}
}
ПРИМЕЧАНИЕ: route и startDestination AKA имя составного объекта не может совпадать.