【问题标题】:Navigating to a Bottom Tab Screen from a Single screen with a button Jetpack Compose使用按钮 Jetpack Compose 从单个屏幕导航到底部选项卡屏幕
【发布时间】:2021-12-18 07:12:27
【问题描述】:

我有一个身份验证页面,在身份验证页面之后,我基本上导航到一个选项卡式应用程序。

问题是,一旦我点击标签,底部栏就会消失。

下面是我的代码的样子

sealed class ScreenM(val route: String) {
    object Landing: Screen("landingm")
    object Tab: Screen("tabm")
}

sealed class Screen(val route: String) {
    object PasswordLogin: Screen("passwordlogin")
    object TabBar: Screen("tabbar")
}

sealed class TabbarItem(var route: String, var icon: Int, var title: String) {
    object Home : TabbarItem("tabhome", R.drawable.ic_home_tab_icon, "Home")
    object Profile : TabbarItem("tabprofile", R.drawable.ic_profile_tab_icon, "Profile")
}

我的应用程序入口点是

@Composable
fun App() {
    val navController = rememberNavController()
    NavHost(navController, startDestination = ScreenM.Landing.route) {
        addLandingTopLevel(navController = navController)
        addTabBarTopLevel(navController = navController)
    }
}

private fun NavGraphBuilder.addLandingTopLevel(
    navController: NavController,
) {
    navigation(
        route = ScreenM.Landing.route,
        startDestination = Screen.Home.route
    ) {
        addPasswordLogin(navController)
    }
}
private fun NavGraphBuilder.addPasswordLogin(navController: NavController) {
    composable(route = Screen.PasswordLogin.route) {
        PasswordLoginView(navController)
    }
}

private fun NavGraphBuilder.addTabBarTopLevel(
    navController: NavController,
) {
    navigation(
        route = ScreenM.Tab.route,
        startDestination = Screen.TabBar.route
    ) {
        addTabBar(navController)
        addHome(navController)
        addProfile(navController)
    }
}

private fun NavGraphBuilder.addTabBar(navController: NavController) {

    composable(route = Screen.TabBar.route) {
        TabBarView(navController)
    }
}

private fun NavGraphBuilder.addHome(navController: NavController) {
    composable(route = TabbarItem.Home.route) {
        HomeView()
    }
}
private fun NavGraphBuilder.addProfile(navController: NavController) {
    composable(route = TabbarItem.Profile.route) {
        ProfileView()
    }
}

我正在像这样触发标签

// ...
NavigationButton(buttonText = "Login", onBackPressed = {
    navController.popBackStack()
}) {
    navController.navigate(ScreenM.Tab.route)
}
// ...

那么我的Tabbar就像

@Composable
fun TabBarView(navController: NavController) {
    Scaffold(
        bottomBar = { BottomNavigationBar(navController) }
    ) {
    }
}

那么底部导航栏是这样的

@Composable
fun BottomNavigationBar(navController: NavController) {
    val items = listOf(
        TabbarItem.Home,
        TabbarItem.Profile
    )
    BottomNavigation(
        backgroundColor = colorResource(id = R.color.white),
        contentColor = Color.Black
    ) {
        items.forEach { item ->
            BottomNavigationItem(
                icon = { Icon(painterResource(id = item.icon), contentDescription = item.title) },
                label = { Text(text = item.title) },
                selectedContentColor = Color.Red,
                unselectedContentColor = Color.Blue.copy(0.4f),
                alwaysShowLabel = true,
                selected = false,
                onClick = {
                    navController.navigate(item.route) {
                        // Pop up to the start destination of the graph to
                        // avoid building up a large stack of destinations
                        // on the back stack as users select items
                        navController.graph.startDestinationRoute?.let { route ->
                            popUpTo(route) {
                                saveState = true
                            }
                        }
                        // Avoid multiple copies of the same destination when
                        // reselecting the same item
                        launchSingleTop = true
                        // Restore state when reselecting a previously selected item
                        restoreState = true
                    }
                }
            )
        }
    }
}

【问题讨论】:

  • 我看到了三个路由:HomeProfileTabBar,而TabBarView 只添加在其中一个内部。当您切换选项卡时,TabBar 路由会消失,TabBarView 也会消失。您需要将其添加到每个目的地内或将其移到NavHost 之外。
  • 我不明白你的建议。请欣赏代码示例。
  • @PhilipDukhov 我尝试了你的建议,标签没有改变。选项卡仍处于选择状态,但屏幕没有变化。
  • 请将您的代码更新为您尝试过的内容
  • 我刚刚将这个添加到 Home 和 Profile composable(route = TabbarItem.Home.route) { TabBarView(navController) } 的 NavGraphBuilder 中

标签: android android-jetpack-compose android-jetpack-navigation


【解决方案1】:

你有两个选择。

  1. 在每个标签内显示BottomNavigationBar

    1.1。不确定代码中的 addTabBar 导航路线是什么,我认为不需要,因为看起来您只有两个选项卡:TabbarItem.HomeTabbarItem.Profile

    1.2。您可以在每个视图中添加BottomNavigationBar,指定所选项目。在HomeView 内部可能是这样的:

    BottomNavigationBar(navController, selectedTab = TabbarItem.Home)
    

    1.3。根据选择的tab,需要选择BottomNavigationBar需要的项

    @Composable
    fun BottomNavigationBar(navController: NavController, selectedTab: TabbarItem) {
        val items = listOf(
            TabbarItem.Home,
            TabbarItem.Profile
        )
        BottomNavigation(
            // ...
        ) {
            items.forEach { item ->
                BottomNavigationItem(
                    // ...
                    selected = selectedTab == item,
                    // ...
    
  2. NavHost 之外有一个导航栏,您可以在documentation 中找到一个示例

【讨论】:

  • addTabbar 是包含 TabBarView 的 NavGraph,它是所有选项卡项(主页、配置文件)的父视图
  • 虽然选项 1 有效,但我只是担心,因为当您使用 android 手机上的后退按钮时,它只是导航回所有之前选择的选项卡。我认为这不是 Tabbar 的行为。
  • 选项 2 感觉是更好的选择。谢谢。
  • @King 要使选项 1 起作用,您需要使用与选项 2 的文档中相同的逻辑:他们正在使用 popUpTo 弹出当前屏幕
猜你喜欢
  • 1970-01-01
  • 2023-02-10
  • 2022-01-20
  • 2023-03-28
  • 1970-01-01
  • 2022-10-23
  • 2023-01-24
  • 2020-03-06
  • 2021-07-02
相关资源
最近更新 更多