Reputation: 363
I want to do navigation with Scaffold
and BottomNavigation
in Jetpack Compose. They are in the MainPage. But when I click the content in the MainPage and navigate to DetailPage, the BottomNavigation
also exist, like the image:
How can I hide the BottomNavigation
in the DetailPage?
Upvotes: 0
Views: 1488
Reputation: 363
I fond a way to do it.
Try to use ViewModle to controll the visibility of BottomNavigation, show it when enter to MainPage and hide it when leave MainPage
// ViewModel
class VM: ViewModel() {
private val _state: MutableLiveData<Boolean> = MutableLiveData(true)
val state: LiveData<Boolean> get() = _state
fun setState(status: Boolean) {
_state.postValue(status)
}
}
// MainPage
@Compose MainPage(vm: VM) {
LaunchedEffect(key1 = true) {
vm.setState(true)
}
DisposableEffect(key1 = true) {
onDispose {
vm.setState(false)
}
}
}
// page contains Scaffold
@Composable
fun Greeting(vm: VM) {
// State of BottomNavigation`s visibility
val state = remember { mutableStateOf<Boolean>(true) }
// read the BottomNavigation`s visibility from ViewModel and send to State
vm.state.observeAsState().value?.let { state.value = it }
Scaffold(bottomBar = {
// show / hide BottomNavigation controlled by State
state.takeIf { it.value }?.let {
BottomNavigation {
list.forEachIndexed { index, label ->
BottomNavigationItem(
label = { Text(text = label) },
selected = index == selectedItem.value,
onClick = { selectedItem.value = index },
icon = {
Icon(
painter = painterResource(id = R.drawable.ic_launcher_foreground),
contentDescription = null
)
})
}
}
}
}) {
NavHost(navController = navController, startDestination = "one") {
composable(route = "one") { PageList(navController, vm) }
composable(route = "detail") { PageDetail(vm) }
}
}
}
If you want ot hide the BottomNavigation quickly, you can hide BottomNavigation before Navigation.
Upvotes: 0
Reputation: 66516
It depends on where you put your NavHost. If it wraps your Scaffold then you navigate that Composable covers entire screen
NavHost(
navController = navController,
startDestination = "start_destination"
) {
composable(route = "start_destination") { ->
Scaffold(){...}
}
}
If NavHost is inside content: @Composable (PaddingValues) -> Unit
, when you navigate while your TopAbbpar
, Tabs
or BottomNavigation
remains on screen
Upvotes: 1
Reputation: 1032
You need to specify which screens you want to show and which screens you dont want; Otherwise it will show to all the screens inside Scaffold
's body (which you have bottomBar
). The code below was from my app.
Create a state which observes any destination changes on the navController
Inside when
you can put any screens that you want to show navigationBar
else just set currentScreen
to NoBottomBar
@Composable
private fun NavController.currentScreen(): State<MainSubScreen> {
val currentScreen = remember { mutableStateOf<MainSubScreen>(MainSubScreen.Home) }
DisposableEffect(key1 = this) {
val listener = NavController.OnDestinationChangedListener { _, destination, _ ->
when {
destination.hierarchy.any { it.route == MainSubScreen.Home.route } -> {
currentScreen.value = MainSubScreen.Home
} else -> currentScreen.value = MainSubScreen.NoBottomBar
}
}
addOnDestinationChangedListener(listener)
}
return currentScreen
}
On the Scaffold where you put ur bottomBar
so you can check if currentScreen
was NoBottomBar
if it was, don't show it
// initialized currentScreeen above
val currentScreen by navController.currentScreen()
Scaffold(
bottomBar = {
if (currentScreen != MainSubScreen.NoBottomBar) {
MainBottomNavigation()
} else Unit
}
) {
// Your screen
}
Upvotes: 2