How to handle the navigation in Navigation3
02:08 04 Dec 2025

I'm doing this post because I'm triying to create an application that has the following navigation:

GlobalNavigation
│
├── AuthActivity (without bottombar)
│   ├── LoginScreen
│   ├── RecoveryScreen
│   ├── SignUpScreen
│
└── MainActivity
     │
     ├── HomeNavTopLevel Graph (Home, Chat, Settings…) → with BottomBar
     │   ├ Home
     │   ├ Profile
     │             
     └── SettingsNavTopLevel Graph (Setting or more screens) → without BottomBar
         ├ One or more screens

My question is the next:

  1. How to avoid the SettingsScreen resize when I navigate to it from a bottom bar screen?

  2. I have to create a NavDisplay for every top level to avoid the bottombar at the settings screeen (even if settings isn't part of the bottom bar).

My current implementation is one NavDisplay inside a Scaffold holding the MainActivity navigation like the example above, hiding the bottomBar when the topLevelStack is not a BottomBar interface, but if you the gif in the bottom you will see that when I navigate to Settings, the bottom bar is hide but the SettingsScreen (Yellow) for a moment has the same height of the bottom bar screens and a few miliseconds (or seconds) it expands along the screen (because the bottom bar was hide).

NOTE: In navigation2 I created a navController for each sub-navigation, like auth and main has a NavHostController but inside of it a create subNavigation with Navigation and just for Home I created another NavHostController to manage the BottomBar navigation.

MainActivity content (Composables):

@Composable
fun MainContent(
    openAuthActivity: () -> Unit,
    navigator: MainNavigator
) {
    SerenoTheme(
        dynamicColor = false
    ) {
        Scaffold(
            modifier = Modifier
                .fillMaxSize(),
            bottomBar = {
                AnimatedVisibility(
                    navigator.topLevelKey is BottomBar,
                    enter = fadeIn(),
                    exit = fadeOut()
                ) {
                    NavigationBar(

                    ) {
                        HomeBottomBarItems.HOME_LEVEL_ROUTES.forEach { (key, item) ->
                            val isSelected = key == navigator.topLevelKey

                            NavigationBarItem(
                                selected = isSelected,
                                onClick = {
                                    navigator.switchTopLevel(key)
                                },
                                icon = {
                                    Icon(
                                        imageVector = item.icon,
                                        contentDescription = null,
                                    )
                                },
                                label = {
                                    Text(
                                        text = stringResource(item.labelStringRes)
                                    )
                                }
                            )
                        }
                    }
                }
            }
        ) { innerPadding ->
            val modifier = remember {
                Modifier.padding(innerPadding)
            }

            MainDisplay(
                modifier = modifier,
                navigator = navigator,
                openAuthActivity = openAuthActivity
            )
        }
    }
}

Mi sealed interface for Destinations:

sealed interface BottomBar

sealed interface MainRoute : NavKey {
    @Serializable
    data object Home : MainRoute, BottomBar

    @Serializable
    data object Profile : MainRoute, BottomBar

    @Serializable
    data object Settings : MainRoute
}

AppNavigator to support multiple back stacks:

class AppNavigator(private val startKey: T) {

    private var topLevelBackStacks: HashMap> = hashMapOf(
        startKey to mutableStateListOf(startKey)
    )

    var topLevelKey by mutableStateOf(startKey)
        private set

    val backStack = mutableStateListOf(startKey)

    private fun updateBackStack() {
        backStack.clear()
        val currentStack = topLevelBackStacks[topLevelKey] ?: emptyList()

        if (topLevelKey == startKey) {
            backStack.addAll(currentStack)
        } else {
            val startStack = topLevelBackStacks[startKey] ?: emptyList()
            backStack.addAll(startStack + currentStack)
        }
    }

    fun switchTopLevel(key: T) {
        if (topLevelBackStacks[key] == null) {
            topLevelBackStacks[key] = mutableStateListOf(key)
        }
        topLevelKey = key
        updateBackStack()
    }

    fun add(key: T) {
        topLevelBackStacks[topLevelKey]?.add(key)
        updateBackStack()
    }

    fun removeLast() {
        val currentStack = topLevelBackStacks[topLevelKey] ?: return

        if (currentStack.size > 1) {
            currentStack.removeLastOrNull()
        } else if (topLevelKey != startKey) {
            topLevelKey = startKey
        }
        updateBackStack()
    }

    fun replaceStack(vararg keys: T) {
        topLevelBackStacks[topLevelKey] = mutableStateListOf(*keys)
        updateBackStack()
    }
}

And a video showing how the application works:
enter image description here

android navigation android-jetpack-compose