Hey I am using BackHandler from this stackoverflow. When I am pressing back button it's not working. Can someone guide me on this.
ResultScreen.kt
#Composable
fun ResultScreen(navController: NavHostController, nearestResultList: List<NearestResult>?) {
SportsResultTheme {
MainScaffold {
BackHandler {
navController.popBackStack()
}
LazyColumn {
if (nearestResultList != null) {
items(nearestResultList) { nearestResult ->
Text(
text = nearestResult.event
)
}
}
}
}
}
}
NavigationGraph.kt
#Composable
internal fun NavigationGraph() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = ScreenRoute.Home.route) {
composable(ScreenRoute.Home.route) {
SetupMainActivityView { nearestResult ->
val nearestResultJson = Uri.encode(Json.encodeToString(nearestResult))
navController.navigate(ScreenRoute.Result.route + "/$nearestResultJson")
}
}
composable(
ScreenRoute.Result.route + "/{$NEAREST_RESULT_JSON}",
arguments = listOf(
navArgument(NEAREST_RESULT_JSON) { type = NearestResultParamType() }
)
) { backStackEntry ->
ResultScreen(navController, backStackEntry.arguments?.getParcelableArrayList(NEAREST_RESULT_JSON))
}
}
}
If you want to see more please visit my repository.
UPDATE
You can see my video link. Anyone know when I back press why my scren flicks ?
UPDATE 2
I added splash screen in my navigation
#Composable
internal fun NavigationGraph() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = ScreenRoute.Splash.route) {
composable(route = ScreenRoute.Splash.route) {
SplashScreen(navController = navController)
}
composable(ScreenRoute.Home.route) {
SetupMainActivityView { nearestResult ->
val nearestResultJson = Uri.encode(Json.encodeToString(nearestResult))
navController.navigate(ScreenRoute.Result.route + "/$nearestResultJson") {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
}
}
composable(
ScreenRoute.Result.route + "/{$NEAREST_RESULT_JSON}",
arguments = listOf(
navArgument(NEAREST_RESULT_JSON) { type = NearestResultParamType() }
)
) { backStackEntry ->
ResultScreen(navController, backStackEntry.arguments?.getParcelableArrayList(NEAREST_RESULT_JSON))
}
}
}
UPDATE 3
navController.navigate(ScreenRoute.Result.route + "/$nearestResultJson") {
popUpTo(ScreenRoute.Home.route) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
Back is not working when I added splash screen
UPDATE 4
#Composable
internal fun NavigationGraph() {
val navController = rememberNavController()
var home by remember {
mutableStateOf<String?>(null)
}
NavHost(navController = navController, startDestination = home ?: ScreenRoute.Splash.route) {
composable(route = ScreenRoute.Splash.route) {
home = ScreenRoute.Home.route
SplashScreen(navController = navController)
}
composable(ScreenRoute.Home.route) {
SetupMainActivityView { nearestResult ->
val nearestResultJson = Uri.encode(Json.encodeToString(nearestResult))
navController.navigate(ScreenRoute.Result.route + "/$nearestResultJson") {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
}
}
composable(
ScreenRoute.Result.route + "/{$NEAREST_RESULT_JSON}",
arguments = listOf(
navArgument(NEAREST_RESULT_JSON) { type = NearestResultParamType() }
)
) { backStackEntry ->
ResultScreen(navController, backStackEntry.arguments?.getParcelableArrayList(NEAREST_RESULT_JSON))
}
}
}
My splash screen not working when initial application load. It direct open my home screen after going to result screen back button again not working.
try navController.navigateUp()
probably the stack has many entries, try using singleton navigation to that stack is not full of undesired entries like
navController.navigate("destination") {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
try to use dynamic start destination like
var home by remember {
mutableStateOf<String?>(null)
}
NavHost(
navController = navController,
startDestination = home?:"splash_destination",
modifier = modifier
) {
composable("splash) {
home = "home_destination"
....
}
.....
}
then go with previous approach
Related
I want to navigate back with different input argument.
I have a ParentScreen and it is using input argument arg (="first"). Code navigates from parent to child by sending newArg (="firstsecond") on button press. When navigating back from child to parent I want parent's input arg to be "fistsecond".
Below I wrote the code (it is not working) to show what I want.
#Composable
fun ParentScreen(
nav: NavHostController,
arg: String = "first"
) {
val newArg = arg + "second"
Button(onClick = {
nav.navigate("child/$newArg") {
popUpTo("parent/$newArg") {
saveState = true
}
}
}) {
Text(text = arg)
}
}
What you may want to do is launch the parent composable as single top, and when navigating from child composable, you can send the new argument and launch it as single top again. Here is how you can achieve if you are using compose navigation;
You can launch ParentScreen for the first time like this;
navController.navigate("parent/first") {
launchSingleTop = true
}
Then navigate to ChildScreen as usual;
navController.navigate("child/firstSecond")
In ChildScreen navigate to ParentSceen like this, this will remove the ChildScreen from the nav stack and launch the ParentScreen as single top, resulting only ParentScreen in the stack with new parameter;
navController.navigate("parent/$newArg") {
launchSingleTop = true
popUpTo("child/{someArg}") {
inclusive = true
}
}
Full code here;
#Composable
fun SampleNavHost(
modifier: Modifier = Modifier,
navController: NavHostController,
onBackClick: () -> Unit,
startDestination: String = "start_dest",
) {
NavHost(
modifier = modifier,
navController = navController,
startDestination = startDestination
) {
composable("start_dest") {
Button(onClick = {
navController.navigate("parent/first") {
launchSingleTop = true
}
}) {
Text(text = "move to parent")
}
}
composable("parent/{someArg}") {
val arg = it.arguments?.getString("someArg").orEmpty()
ParentScreen(
title = arg,
navStackSize = navController.backQueue.size.toString(),
onButtonClick = {
navController.navigate("child/firstSecond")
}
)
}
composable("child/{someArg}") {
val arg = it.arguments?.getString("someArg").orEmpty()
val newArg = arg + "second"
ChildScreen(
title = arg,
onButtonClick = {
navController.navigate("parent/$newArg") {
launchSingleTop = true
// this will navigate current composable from stack when navigating
popUpTo("child/{someArg}") {
inclusive = true
}
}
}
)
}
}
}
#Composable
fun ParentScreen(
title: String,
navStackSize: String,
onButtonClick: () -> Unit,
) {
Column {
Text(text = "Parent Screen, stack size: $navStackSize")
Button(onClick = onButtonClick) {
Text(text = title)
}
}
}
#Composable
fun ChildScreen(
title: String,
onButtonClick: (String) -> Unit,
) {
Column {
Text(text = "Child Screen")
Button(onClick = { onButtonClick(title) }) {
Text(text = title)
}
}
}
I have an Android app using compose navigation. Navigating between its three screens - Home, Calendar, More - is done via a bottom bar:
// onBottomBarItemClick from https://developer.android.com/jetpack/compose/navigation#bottom-nav:
navController.navigate(destination) {
popUpTo("HOME") {
saveState = true
}
launchSingleTop = true
restoreState = true
}
Up until now everything is working as expected.
However, i sometimes want to pass an argument from Home to Calendar - see screenshot.
This is where things start to break apart.
HomeScreen(
onNavigateToCalendar = { argument ->
navController.navigate("CALENDAR?ARG=$argument") {
popUpTo("HOME") {
saveState = true
}
launchSingleTop = true
restoreState = false
}
}
)
If i now do the following...
Start the app fresh - i'm at home
Navigate to Calendar with argument A - it shows A
Navigate to Home via BottomBar
Navigate to Calendar with argument B - it shows B
Navigate to More
Navigate to Calendar via BottomBar - it shows A not B - which is weird.
I believe i have tried every possible combination of saveState / launchSingleTop / restoreState, but all of them had some issues. Can someone help me please? I'm loking for a solution where:
Calendar will always display an argument when explicitly provided
Calendar will display none or the last argument, when no argument is provided
"Back" works correctly: Navigating back from Calendar / More should lead to Home
State (e.g. scroll state) is kept as you'd expect
Minimal Example:
#Composable
fun MainScreen() {
val navController = rememberNavController()
Scaffold(
content = { paddingValues ->
NavHost(
navController = navController,
startDestination = "HOME",
modifier = Modifier.padding(paddingValues)
) {
composable("HOME") {
HomeScreen(
onNavigateToCalendar = { argument ->
navController.navigate("CALENDAR?ARG=$argument") {
popUpTo("HOME") {
saveState = true
}
launchSingleTop = true
restoreState = false
}
}
)
}
composable("CALENDAR?ARG={ARG}") {
CalendarScreen(it.arguments?.getString("ARG"))
}
composable("MORE") {
MoreScreen()
}
}
},
bottomBar = {
MyBottomBar(
onClick = { destination ->
navController.navigate(destination) {
popUpTo("HOME") {
saveState = true
}
launchSingleTop = true
restoreState = true
}
}
)
}
)
}
#Composable
private fun HomeScreen(
onNavigateToCalendar: (argument: String) -> Unit
) {
Column {
Text("HOME")
Button(
onClick = { onNavigateToCalendar("A") },
content = { Text("Navigate to CALENDAR with argument = A") },
)
Button(
onClick = { onNavigateToCalendar("B") },
content = { Text("Navigate to CALENDAR with argument = B") },
)
}
}
#Composable
private fun CalendarScreen(argument: String?) {
Text("CALENDAR with argument = $argument")
}
#Composable
private fun MoreScreen() {
Text("MORE")
}
#Composable
private fun MyBottomBar(
onClick: (destination: String) -> Unit
) {
BottomAppBar {
listOf("HOME", "CALENDAR", "MORE").forEach { destination ->
BottomNavigationItem(
selected = false, // TODO - not important for now
icon = {},
label = { Text(destination) },
onClick = { onClick(destination) },
)
}
}
}
I'm developing an android application using Jetpack Compose. For now, I have several screens (Login, Register, Messages, Profile and Settings). I used a root NavGraph to host the navGraphs of authentication and main screen (See the codes below).
RootNavGraph.kt
#Composable
fun RootNavGraph(navController: NavHostController) {
NavHost(
navController = navController,
startDestination = AUTHENTICATION_ROUTE,
route = ROOT_ROUTE
) {
authNavGraph(navController = navController)
bottomNavGraph(navController = navController)
}
}
authNavGraph.kt
fun NavGraphBuilder.authNavGraph(navController: NavHostController) {
navigation(
startDestination = AuthenticationScreens.Login.route,
route = AUTHENTICATION_ROUTE
) {
composable(route = AuthenticationScreens.Login.route) {
LoginPage(navController = navController)
}
composable(route = AuthenticationScreens.Register.route) {
RegisterPage(navController = navController)
}
}
}
bottomNavGraph.kt
fun NavGraphBuilder.bottomNavGraph(navController: NavHostController) {
navigation(
startDestination = BottomBarScreen.Messages.route,
route = BOTTOM_ROOT_ROUTE
) {
composable(route = BottomBarScreen.Messages.route) {
Messages()
}
composable(route = BottomBarScreen.Profile.route) {
Profile(navController = navController)
}
composable(route = BottomBarScreen.Settings.route) {
Settings()
}
}
}
I have the MainScreen that contains the bottom navigation bar.
#Composable
fun MainScreen() {
val navController = rememberNavController()
Scaffold(
bottomBar = {
BottomBar(navController = navController)
}
) {
//bottomNavGraph(navController)
}
}
#Composable
fun BottomBar(navController: NavHostController) {
val screens = listOf(
BottomBarScreen.Messages,
BottomBarScreen.Profile,
BottomBarScreen.Settings
)
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
BottomNavigation() {
screens.forEach { screen ->
AddItem(
screen = screen,
currentDestination = currentDestination,
navController = navController
)
}
}
}
#Composable
fun RowScope.AddItem(
screen: BottomBarScreen,
currentDestination: NavDestination?,
navController: NavHostController
) {
BottomNavigationItem(
label = {
Text(text = screen.title)
},
alwaysShowLabel = false,
icon = {
Icon(imageVector = screen.icon, contentDescription = "Navigation Icon")
},
selected = currentDestination?.hierarchy?.any {
it.route == screen.route
} == true,
unselectedContentColor = LocalContentColor.current.copy(alpha = ContentAlpha.disabled),
onClick = {
navController.navigate(screen.route) {
popUpTo(navController.graph.findStartDestination().id)
launchSingleTop = true
}
}
)
}
My problem is: after switching to use the nested nav graphs, I cannot use the bottomNavGraph directly in the MainScreen since it's no longer a NavHost and thus the bottom navigation bar isn't showing. I would appreciate if any one can help me with that.
For bottom navigation use the NavHost to show the bottom bar
fun HomeNavGraph(navHostController: NavHostController) {
NavHost(
navController = navHostController,
route = Graph.Home,
startDestination = BottomBar.Home.route
) {
composable(BottomBar.Home.route){
HomeScreenContent()
}
then use this graph in your homescreen scaffold
fun HomeScreen(navController: NavHostController = rememberNavController()) {
Scaffold(bottomBar = {
BottomNavigation(navController = navController)
}) {
HomeNavGraph(navHostController = navController)
}
at last in the rootgraph use this homescreen class with your rootgraph route
fun RootNavigationGraphBuilder(navHostController: NavHostController) {
NavHost(navController = navHostController, startDestination = Graph.Authentication, route = Graph.Root) {
authNavGraph(navHostController)
composable(route = Graph.Home){
HomeScreen()
}
}
here are sample routes which i use in my code
object Graph {
const val Root = "root_graph"
const val Authentication = "auth_graph"
const val Home = "home_graph"
}
I have implemented the accompanist navigation animation library in my project and have stumbled into two issues. The first issue is that the animations aren't being applied when navigating from one screen to another. The second issue is that the "back" of the system closes the app to the background instead of returning to the previous screen.
Here is the layout of the app starting from the MainActivity.
MainActivity.kt
#ExperimentalAnimationApi
#AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val preDrawListener = ViewTreeObserver.OnPreDrawListener { false }
override fun onCreate(savedInstanceState: Bundle?) {
setTheme(R.style.MyHomeTheme)
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
val content: View = findViewById(android.R.id.content)
content.viewTreeObserver.addOnPreDrawListener(preDrawListener)
lifecycleScope.launch {
setContent {
val systemUiController = rememberSystemUiController()
SideEffect {
systemUiController.setStatusBarColor(
color = Color.Transparent,
darkIcons = true
)
systemUiController.setNavigationBarColor(
color = Color(0x40000000),
darkIcons = false
)
}
MyHomeApp(
currentRoute = Destinations.Welcome.WELCOME_ROUTE
)
}
unblockDrawing()
}
}
private fun unblockDrawing() {
val content: View = findViewById(android.R.id.content)
content.viewTreeObserver.removeOnPreDrawListener(preDrawListener)
content.viewTreeObserver.addOnPreDrawListener { true }
}
}
MyHomeApp.kt
#ExperimentalAnimationApi
#Composable
fun MyHomeApp(currentRoute: String) {
MyHomeTheme {
ProvideWindowInsets {
val navController = rememberAnimatedNavController()
val scaffoldState = rememberScaffoldState()
val darkTheme = isSystemInDarkTheme()
val items = listOf(
HomeTab.Dashboard,
HomeTab.Details,
HomeTab.Settings
)
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
val bottomPaddingModifier = if (currentDestination?.route?.contains("welcome") == true) {
Modifier
} else {
Modifier.navigationBarsPadding()
}
Scaffold(
modifier = Modifier
.fillMaxSize()
.then(bottomPaddingModifier),
scaffoldState = scaffoldState,
bottomBar = {
if (currentDestination?.route in items.map { it.route }) {
BottomNavigation {
items.forEach { screen ->
BottomNavigationItem(
label = { Text(screen.title) },
icon = {},
selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
onClick = {
navController.navigate(screen.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
popUpTo(navController.graph.findStartDestination().id) {
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
}
}
)
}
}
}
}
) { innerPadding ->
MyHomeNavGraph(
modifier = Modifier.padding(innerPadding),
navController = navController,
startDestination = navBackStackEntry?.destination?.route ?: currentRoute
)
}
}
}
}
sealed class HomeTab(
val route: String,
val title: String
) {
object Dashboard : HomeTab(
route = Destinations.Home.HOME_DASHBOARD,
title = "Dashboard"
)
object Details : HomeTab(
route = Destinations.Home.HOME_DETAILS,
title = "Details"
)
object Settings : HomeTab(
route = Destinations.Home.HOME_SETTINGS,
title = "Settings"
)
}
MyHomeNavGraph.kt
#ExperimentalAnimationApi
#Composable
fun MyHomeNavGraph(
modifier: Modifier = Modifier,
navController: NavHostController,
startDestination: String
) {
val actions = remember(navController) { Actions(navController = navController) }
AnimatedNavHost(
modifier = modifier,
navController = navController,
startDestination = startDestination
) {
composable(
route = Destinations.Welcome.WELCOME_ROUTE,
enterTransition = {
when (initialState.destination.route) {
Destinations.Welcome.WELCOME_LOGIN_ROUTE ->
slideIntoContainer(towards = AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700))
else -> null
}
},
exitTransition = {
when (targetState.destination.route) {
Destinations.Welcome.WELCOME_LOGIN_ROUTE ->
slideOutOfContainer(towards = AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700))
else -> null
}
},
popEnterTransition = {
when (initialState.destination.route) {
Destinations.Welcome.WELCOME_LOGIN_ROUTE ->
slideIntoContainer(towards = AnimatedContentScope.SlideDirection.Right, animationSpec = tween(700))
else -> null
}
},
popExitTransition = {
when (targetState.destination.route) {
Destinations.Welcome.WELCOME_LOGIN_ROUTE ->
slideOutOfContainer(towards = AnimatedContentScope.SlideDirection.Right, animationSpec = tween(700))
else -> null
}
}
) {
WelcomeScreen(
navigateToLogin = actions.navigateToWelcomeLogin,
navigateToRegister = actions.navigateToWelcomeRegister,
)
}
composable(
route = Destinations.Welcome.WELCOME_LOGIN_ROUTE,
enterTransition = {
when (initialState.destination.route) {
Destinations.Welcome.WELCOME_ROUTE ->
slideIntoContainer(towards = AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700))
else -> null
}
},
exitTransition = {
when (targetState.destination.route) {
Destinations.Welcome.WELCOME_ROUTE ->
slideOutOfContainer(towards = AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700))
else -> null
}
},
popEnterTransition = {
when (initialState.destination.route) {
Destinations.Welcome.WELCOME_ROUTE ->
slideIntoContainer(towards = AnimatedContentScope.SlideDirection.Right, animationSpec = tween(700))
else -> null
}
},
popExitTransition = {
when (targetState.destination.route) {
Destinations.Welcome.WELCOME_ROUTE ->
slideOutOfContainer(towards = AnimatedContentScope.SlideDirection.Right, animationSpec = tween(700))
else -> null
}
}
) {
WelcomeLoginScreen(
// Arguments will be passed to navigate to the home screen or other
)
}
}
}
class Actions(val navController: NavHostController) {
// Welcome
val navigateToWelcome = {
navController.navigate(Destinations.Welcome.WELCOME_ROUTE)
}
val navigateToWelcomeLogin = {
navController.navigate(Destinations.Welcome.WELCOME_LOGIN_ROUTE)
}
}
For simplicity's sake, you can assume that the screens are juste a box with a button in the middle which executes the navigation when they are clicked.
The accompanist version I am using is 0.24.1-alpha (the latest as of this question) and I am using compose version 1.2.0-alpha02 and kotlin 1.6.10.
In terms of animation, the only difference I can see with the accompanist samples is that I don't pass the navController to the screens but I don't see how that could be an issue.
And in terms of using the system back which should return to a previous, I'm genuinely stuck in terms of what could cause the navigation to close the app instead of going back. On other projects, the system back works just fine but not with this one. Is the use of the accompanist navigation incompatible ? I'm not sure.
Any help is appreciated!
I found the source of the issue.
The fact that I was setting the startDestination parameter to navBackStackEntry?.destination?.route ?: currentRoute meant that each change to the navBackStackEntry recomposed the MyHomeNavGraph and hence the backstack was reset upon the recomposition.
Note to self, watch out when copying navigation from multiple sources!
I have a auth page and after the auth page, I basically navigate to a Tabbed application.
The problem is that bottom bar disappears once I click on tab.
Below is what my code looks like
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")
}
my application entry point is
#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()
}
}
I am triggering the Tab like this
// ...
NavigationButton(buttonText = "Login", onBackPressed = {
navController.popBackStack()
}) {
navController.navigate(ScreenM.Tab.route)
}
// ...
Then my Tabbar is like
#Composable
fun TabBarView(navController: NavController) {
Scaffold(
bottomBar = { BottomNavigationBar(navController) }
) {
}
}
Then bottom navigation Bar is like this
#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
}
}
)
}
}
}
You have two options.
Displaying BottomNavigationBar inside each tab
1.1. Not sure what's addTabBar navigation route in your code, I don't think it's need, as looks like you only have two tabs: TabbarItem.Home and TabbarItem.Profile.
1.2. You can add BottomNavigationBar inside each view, specifying the selected item. Inside HomeView it can look like this:
BottomNavigationBar(navController, selectedTab = TabbarItem.Home)
1.3. Depending on the selected tab, you need to select the needed item of BottomNavigationBar
#Composable
fun BottomNavigationBar(navController: NavController, selectedTab: TabbarItem) {
val items = listOf(
TabbarItem.Home,
TabbarItem.Profile
)
BottomNavigation(
// ...
) {
items.forEach { item ->
BottomNavigationItem(
// ...
selected = selectedTab == item,
// ...
Having a single navigation bar outside of NavHost, you can find an example in documentation