android - 当导航到可组合时,我们如何隐藏 BottomAppBar(包含导航)?

标签 android kotlin navigation android-jetpack-compose

我有个问题。
问题是当我导航到“添加问题”屏幕时,我不知道如何隐藏底部应用程序栏。
我需要你的帮助。
这是底部应用栏的 MyScreen

@Composable
fun Navigation() {
    val navController = rememberNavController()
    val items = listOf(Screen.Home, Screen.Search, Screen.Notifications, Screen.Profil)

    Scaffold(
        bottomBar = {
            bottomAppNavigation(navController = navController, items)

        }
    ) {
        Box(modifier = Modifier.padding(it)) {
            ScreenController(navController = navController)
        }

    }
}
这是我的带有 navHost 的 Controller
@ExperimentalComposeUiApi
@Composable
fun ScreenController(navController: NavHostController) {
    NavHost(navController = navController, startDestination = Screen.Home.route) {
        composable(Screen.Home.route) {
            HomeScreen(navController)
        }
        composable(Screen.Search.route) {
            SearchScreen(navController, it)
        }
        composable(Screen.Notifications.route) {

        }
        composable(Screen.Profil.route) {
            user_profil()
        }
        composable("Ask_question") {
            AskScreen(navController)
        }
    }
}
我认为这个问题是因为这就像 Activity 和 fragment ,我有一个可组合屏幕所在的盒子,我所有的页面都在他里面。

最佳答案

我建议你使用 AnimatedVisibility对于 BottomNavigation小部件,我认为这是最清晰的撰写方式。

  • 您应该使用 remeberSaveable存储 BottomBar 的状态:
  • // State of bottomBar, set state to false, if current page route is "car_details"
    val bottomBarState = rememberSaveable { (mutableStateOf(true)) }
    
  • 在可组合函数中,我们使用了 when对于BottomBar的控制状态,下面我们设置bottomBarStatetrue ,如果我们想显示BottomBar,否则我们设置bottomBarStatefalse :
  • val navController = rememberNavController()
    
    // Subscribe to navBackStackEntry, required to get current route
    val navBackStackEntry by navController.currentBackStackEntryAsState()
    
    // Control BottomBar
    when (navBackStackEntry?.destination?.route) {
        "cars" -> {
            // Show BottomBar
            bottomBarState.value = true
        }
        "bikes" -> {
            // Show BottomBar
            bottomBarState.value = true
        }
        "settings" -> {
            // Show BottomBar
            bottomBarState.value = true
        }
        "car_details" -> {
            // Hide BottomBar
            bottomBarState.value = false
        }
    }
    
    Scaffold(
        bottomBar = {
            BottomBar(
                navController = navController,
                bottomBarState = bottomBarState
            )
        },
        content = {
            NavHost(
                navController = navController,
                startDestination = NavigationItem.Cars.route,
            ) {
                composable(NavigationItem.Cars.route) {
                    CarsScreen(
                        navController = navController,
                    )
                }
                composable(NavigationItem.Bikes.route) {
                    BikesScreen(
                        navController = navController
                    )
                }
                composable(NavigationItem.Settings.route) {
                    SettingsScreen(
                        navController = navController,
                    )
                }
                composable(NavigationItem.CarDetails.route) {
                    CarDetailsScreen(
                        navController = navController,
                    )
                }
            }
        }
    )
    
  • BottomNavigation里面 AnimatedVisibility , 设置 visible来自 bottomBarState 的值并设置enterexit动画,就我而言,我使用 slideInVertically对于 enter动画和slideOutVertically对于 exit动画:
  • AnimatedVisibility(
            visible = bottomBarState.value,
            enter = slideInVertically(initialOffsetY = { it }),
            exit = slideOutVertically(targetOffsetY = { it }),
            content = {
                BottomNavigation {
                    val navBackStackEntry by navController.currentBackStackEntryAsState()
                    val currentRoute = navBackStackEntry?.destination?.route
    
                    items.forEach { item ->
                        BottomNavigationItem(
                            icon = {
                                Icon(
                                    painter = painterResource(id = item.icon),
                                    contentDescription = item.title
                                )
                            },
                            label = { Text(text = item.title) },
                            selected = currentRoute == item.route,
                            onClick = {
                                navController.navigate(item.route) {
                                    popUpTo(navController.graph.findStartDestination().id) {
                                        saveState = true
                                    }
                                    launchSingleTop = true
                                    restoreState = true
                                }
                            }
                        )
                    }
                }
            }
        )
    
    MainActivity 的完整代码:
    package codes.andreirozov.bottombaranimation
    
    import android.os.Bundle
    import androidx.activity.ComponentActivity
    import androidx.activity.compose.setContent
    import androidx.compose.animation.AnimatedVisibility
    import androidx.compose.animation.ExperimentalAnimationApi
    import androidx.compose.animation.slideInVertically
    import androidx.compose.animation.slideOutVertically
    import androidx.compose.material.*
    import androidx.compose.runtime.*
    import androidx.compose.runtime.saveable.rememberSaveable
    import androidx.compose.ui.res.painterResource
    import androidx.navigation.NavController
    import androidx.navigation.NavGraph.Companion.findStartDestination
    import androidx.navigation.compose.NavHost
    import androidx.navigation.compose.composable
    import androidx.navigation.compose.currentBackStackEntryAsState
    import androidx.navigation.compose.rememberNavController
    import codes.andreirozov.bottombaranimation.screens.BikesScreen
    import codes.andreirozov.bottombaranimation.screens.CarDetailsScreen
    import codes.andreirozov.bottombaranimation.screens.CarsScreen
    import codes.andreirozov.bottombaranimation.screens.SettingsScreen
    import codes.andreirozov.bottombaranimation.ui.theme.BottomBarAnimationTheme
    
    @ExperimentalAnimationApi
    class MainActivity : ComponentActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContent {
                BottomBarAnimationApp()
            }
        }
    }
    
    @ExperimentalAnimationApi
    @Composable
    fun BottomBarAnimationApp() {
    
        // State of bottomBar, set state to false, if current page route is "car_details"
        val bottomBarState = rememberSaveable { (mutableStateOf(true)) }
    
        BottomBarAnimationTheme {
            val navController = rememberNavController()
    
            // Subscribe to navBackStackEntry, required to get current route
            val navBackStackEntry by navController.currentBackStackEntryAsState()
    
            // Control BottomBar
            when (navBackStackEntry?.destination?.route) {
                "cars" -> {
                    // Show BottomBar
                    bottomBarState.value = true
                }
                "bikes" -> {
                    // Show BottomBar
                    bottomBarState.value = true
                }
                "settings" -> {
                    // Show BottomBar
                    bottomBarState.value = true
                }
                "car_details" -> {
                    // Hide BottomBar
                    bottomBarState.value = false
                }
            }
    
            Scaffold(
                bottomBar = {
                    BottomBar(
                        navController = navController,
                        bottomBarState = bottomBarState
                    )
                },
                content = {
                    NavHost(
                        navController = navController,
                        startDestination = NavigationItem.Cars.route,
                    ) {
                        composable(NavigationItem.Cars.route) {
                            CarsScreen(
                                navController = navController,
                            )
                        }
                        composable(NavigationItem.Bikes.route) {
                            BikesScreen(
                                navController = navController
                            )
                        }
                        composable(NavigationItem.Settings.route) {
                            SettingsScreen(
                                navController = navController,
                            )
                        }
                        composable(NavigationItem.CarDetails.route) {
                            CarDetailsScreen(
                                navController = navController,
                            )
                        }
                    }
                }
            )
        }
    }
    
    @ExperimentalAnimationApi
    @Composable
    fun BottomBar(navController: NavController, bottomBarState: MutableState<Boolean>) {
        val items = listOf(
            NavigationItem.Cars,
            NavigationItem.Bikes,
            NavigationItem.Settings
        )
    
        AnimatedVisibility(
            visible = bottomBarState.value,
            enter = slideInVertically(initialOffsetY = { it }),
            exit = slideOutVertically(targetOffsetY = { it }),
            content = {
                BottomNavigation {
                    val navBackStackEntry by navController.currentBackStackEntryAsState()
                    val currentRoute = navBackStackEntry?.destination?.route
    
                    items.forEach { item ->
                        BottomNavigationItem(
                            icon = {
                                Icon(
                                    painter = painterResource(id = item.icon),
                                    contentDescription = item.title
                                )
                            },
                            label = { Text(text = item.title) },
                            selected = currentRoute == item.route,
                            onClick = {
                                navController.navigate(item.route) {
                                    popUpTo(navController.graph.findStartDestination().id) {
                                        saveState = true
                                    }
                                    launchSingleTop = true
                                    restoreState = true
                                }
                            }
                        )
                    }
                }
            }
        )
    }
    
    结果:
    BottomBar animation
    不要忘记使用 @ExperimentalAnimationApi撰写功能的注释。
    更新:使用 Compose 1.1.0 及更高版本 @ExperimentalAnimationApi不需要。
    2022 年 2 月 22 日更新:我做了一些研究,并更新了点 2。现在我们使用 when用于控制 bottomBarState .
    完整代码可在 gitHub 上找到:
    https://github.com/AndreiRoze/BottomBarAnimation
    官方文档中提供的动画示例:
    https://developer.android.com/jetpack/compose/animation

    关于android - 当导航到可组合时,我们如何隐藏 BottomAppBar(包含导航)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67575664/

    相关文章:

    css - 如何处理具有固定垂直和水平导航的页面

    android - WebView 的 loadUrl 方法是否在 UI 线程上运行?

    android - 如何检查文件是否存在于Android设备的特定文件夹中

    java - 在 java.lang.reflect.Proxy 对象上调用扩展函数时的 Kotlin 奇怪行为

    android - Proguard - 不要混淆 Kotlin 数据类

    css - 导航菜单中的间距

    jsf - 当preRenderView事件跳转到嵌套后备bean中的另一个 View 时,面对的消息未显示

    javascript - 是否可以通过网络浏览器 api 访问移动设备的电池状态或充电?

    Android 收听主页按钮

    java - 具有不同 PathVariable 的相同 rest 端点