简体   繁体   中英

How can we hide BottomAppBar (with navigation include) when navigate to composable?

I have a problem.

The problem is that i don't know how to hide bottom app bar when i'm navigating to a "add question" screen.

I need your help please.

This is MyScreen with the bottom app bar

@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)
        }

    }
}

And this is My controller with navHost

@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)
        }
    }
}

The problem i think it's because that's like activity and fragment, i have a box where the composable screen goes, and all my pages are in him.

If you want to hide the BottomBar just don't output it.

Something like:

Scaffold(
    bottomBar = {
        if (currentRoute != "xxxx") {
            BottomAppBar() {
               //....
            }
        }
    },

where the currentRoute is (using at least Navigation Compose 2.4.0-alpha01):

val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry.destination.route

I recommend you use AnimatedVisibility for BottomNavigation widget, im my opinion it's clearest way for compose.

  1. You should use remeberSaveable to store state of BottomBar:
// State of bottomBar, set state to false, if current page route is "car_details"
val bottomBarState = rememberSaveable { (mutableStateOf(true)) }
  1. In each composable routes inside of NavHost , you should update state of BottomBar, below we set bottomBarState to true , if we would like to show BottomBar, otherwise we set bottomBarState to false :
val navController = rememberNavController()
        Scaffold(
            bottomBar = {
                BottomBar(
                    navController = navController,
                    bottomBarState = bottomBarState
                )
            },
            content = {
                NavHost(
                    navController = navController,
                    startDestination = NavigationItem.Cars.route,
                ) {
                    composable(NavigationItem.Cars.route) {
                        // show BottomBar
                        bottomBarState.value = true
                        CarsScreen(
                            navController = navController,
                        )
                    }
                    composable(NavigationItem.Bikes.route) {
                        // show BottomBar
                        bottomBarState.value = true
                        BikesScreen(
                            navController = navController
                        )
                    }
                    composable(NavigationItem.Settings.route) {
                        // show BottomBar
                        bottomBarState.value = true
                        SettingsScreen(
                            navController = navController,
                        )
                    }
                    composable(NavigationItem.CarDetails.route) {
                        // hide BottomBar
                        bottomBarState.value = false
                        CarDetailsScreen(
                            navController = navController,
                        )
                    }
                }
            }
        )
  1. Put BottomNavigation inside AnimatedVisibility , set visible value from bottomBarState and set enter and exit animation, in my case I use slideInVertically for enter animation and slideOutVertically for exit animation:
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
                            }
                        }
                    )
                }
            }
        }
    )

Full code of 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()
        Scaffold(
            bottomBar = {
                BottomBar(
                    navController = navController,
                    bottomBarState = bottomBarState
                )
            },
            content = {
                NavHost(
                    navController = navController,
                    startDestination = NavigationItem.Cars.route,
                ) {
                    composable(NavigationItem.Cars.route) {
                        // show BottomBar
                        bottomBarState.value = true
                        CarsScreen(
                            navController = navController,
                        )
                    }
                    composable(NavigationItem.Bikes.route) {
                        // show BottomBar
                        bottomBarState.value = true
                        BikesScreen(
                            navController = navController
                        )
                    }
                    composable(NavigationItem.Settings.route) {
                        // show BottomBar
                        bottomBarState.value = true
                        SettingsScreen(
                            navController = navController,
                        )
                    }
                    composable(NavigationItem.CarDetails.route) {
                        // hide BottomBar
                        bottomBarState.value = false
                        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
                            }
                        }
                    )
                }
            }
        }
    )
}

Result:

底栏动画

Don't forget to use @ExperimentalAnimationApi annotation for compose functions.

Full code available on gitHub: https://github.com/AndreiRoze/BottomBarAnimation

Examples of animations available in the official documentation: https://developer.android.com/jetpack/compose/animation

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM