提问者:小点点

以编程方式导航到底部导航选项卡


我有一个带有Jetpack撰写的屏幕,它有一个底部导航和一个导航主机。

在某个时刻,我向该屏幕返回某个值,其效果必须是它应该导航到其中一个选项卡。

如果我只是使用navController.导航(目标),那么我有以下错误:

所以我想这不是正确的方法。

如何使用NavController以编程方式导航?

===

编辑:失败的代码:

const valMAIN_COMPOSABLE_ID="main"

sealed class MainTabNavigation(
    val route: String,
    @StringRes val resourceId: Int,
    @DrawableRes val drawableId: Int
) {
    object Tab1 : MainTabNavigation("tab1", R.string.shop_tabName, R.drawable.tab1)
    object Tab2 :
        MainTabNavigation("tab2", R.string.wardrobe_tabName, R.drawable.tab2)

    object Tab3 : MainTabNavigation("tab3", R.string.cart_tabName, R.drawable.tab3)
    object Tab4 : MainTabNavigation("tab4", R.string.profile_tabName, R.drawable.tab4)
}

private val navItems = listOf(
    MainTabNavigation.Tab1, MainTabNavigation.Tab2,
    MainTabNavigation.Tab3, MainTabNavigation.Tab4
)

@Composable
fun MainScreen(navController: NavController) {
    val mainNavController = rememberNavController()

    var goToTab2 = false

    val commManager by inject<ComposableCommManager>()
    val comm = commManager.readComm(MAIN_COMPOSABLE_ID)
    comm?.let {
        if (it.communication == "go_to_tab2") {
            goToTab2 = true
        }
    }

    if (goToTab2) {
        // TODO This line fails
        mainNavController.navigate(MainTabNavigation.Tab3.route)
    }

    Scaffold(
        modifier = Modifier.systemBarsPadding(),
        bottomBar = {
            BottomNavigation(
                backgroundColor = Color.White,
                contentColor = MaterialTheme.colors.primary
            ) {
                val navBackStackEntry by mainNavController.currentBackStackEntryAsState()
                val currentDestination = navBackStackEntry?.destination

                navItems.forEach { tab ->
                    BottomNavigationItem(
                        icon = {
                            Icon(
                                painterResource(id = tab.drawableId),
                                contentDescription = null
                            )
                        },
                        label = { Text(stringResource(tab.resourceId)) },
                        alwaysShowLabel = false,
                        selected = currentDestination?.hierarchy?.any { it.route == tab.route } == true,
                        onClick = {
                            mainNavController.navigate(tab.route) {
                                popUpTo(mainNavController.graph.findStartDestination().id) {
                                    saveState = true
                                }
                                launchSingleTop = true
                                restoreState = true
                            }
                        }
                    )
                }
            }
        }
    ) { innerPadding ->
        NavHost(
            mainNavController,
            startDestination = if (goToTab2) {
                MainTabNavigation.Tab3.route
            } else {
                startMainDestination
            },
            Modifier.padding(innerPadding)
        ) {
            composable(MainTabNavigation.Tab1.route) {
                ShopTab(navController)
            }
            composable(MainTabNavigation.Tab2.route) {
                WardrobeTab(navController, mainNavController)
            }
            composable(MainTabNavigation.Tab3.route) {
                CartTab(navController, mainNavController)
            }
            composable(MainTabNavigation.Tab4.route) {
                ProfileTab(navController)
            }
        }
    }
}

共1个答案

匿名用户

 if (goToTab2) {
    mainNavController.navigate(MainTabNavigation.Tab3.route)
}

在jetpack Comment中,你不能使用这样的代码,因为每次在recomposion中,代码都会重新运行。你必须把那部分放在可点击的地方。或者把你的代码放在“命令读取”中查看模型,并在每个ON_RESUME检查那个值。

或者在ON_RESUME块中读取该值(但viewModel会更好)。

@Composable
fun OnLifecycleEvent(onEvent: (owner: LifecycleOwner, event: Lifecycle.Event) -> Unit) {
    val eventHandler = rememberUpdatedState(onEvent)
    val lifecycleOwner = rememberUpdatedState(LocalLifecycleOwner.current)

    DisposableEffect(lifecycleOwner.value) {
        val lifecycle = lifecycleOwner.value.lifecycle
        val observer = LifecycleEventObserver { owner, event ->
            eventHandler.value(owner, event)
        }

        lifecycle.addObserver(observer)
        onDispose {
            lifecycle.removeObserver(observer)
        }
    }
}

像这样使用它

OnLifecycleEvent { _, event ->
    when (event) {
        Lifecycle.Event.ON_RESUME -> {
            mainPageViewModel.setEvent(MainPageContract.Event.OnResume)
        }
        else -> Unit
    }
}