How to correctly use BottomBar (NavigationBar) for top level destination screens?
M

0

2

So I had such UI structure at app top level composable (Scaffold to add bottom bar)

Scaffold(
    contentWindowInsets = WindowInsets(0, 0, 0, 0),
    bottomBar = {
        if (appState.shouldShowBottomBarAndDrawer) {
            AppBottomBar(
                currentAppDestination = appState.currentDestination,
                onTopLevelScreenNavigate = ...
            )
        }
    }
) { innerPadding ->
    AppNavGraph(
        modifier = Modifier
            .fillMaxSize()
            .padding(innerPadding)
            .consumeWindowInsets(innerPadding)
        startDestination = appStartScreen,
        navController = appState.navController,
        modifier = Modifier

    )
}

Each screen has its own Scaffold to add top bars with different actions and so on, so we can't really move such things to top level composable

The problem using this approach is when I switched from NavHost to AnimatedNavHost for animations it works ugly when you navigate up from screen without bottom bar to the screen with bottom (top level destination), so basically during animations we can see both screens and it adds navigation bar empty padding for screen without bottom bar during animation because appState.shouldShowBottomBarAndDrawer returns true now and each screen has that bottom padding for navigation bar, so content goes up, screen animation transition looks ugly.

But also there is different issue, not just animations, the vertical scroll jumps (for screens with lists or just scrollable) when state of bottom bar changes.

So there are minimum two issues with using Scaffold and bottom bar at top level destination - animations and scroll is not restored to the correct previous position when navigating up, it shifts every time

I decided to fix it the next way (replace Scaffold to Box for top level composable):

Box(modifier = Modifier.fillMaxSize()) {
    AppNavGraph(
        startDestination = appStartScreen,
        navController = appState.navController,
        modifier = Modifier.fillMaxSize()
    )

    Box(modifier = Modifier.align(Alignment.BottomCenter)) {
        AppBottomBar(
            currentAppDestination = appState.currentDestination,
            onTopLevelScreenNavigate = ...
        )
    }
}

Basically keep NavHost always with the same size, so it would not depend on bottom bar visibility state

But now I need to add bottom navigation bar padding for top level destination screens, I tried adding .padding(WindowInsets.navigationBars.asPaddingValues()) and .navigationBarsPadding() but it didn't add any padding:

@Composable
fun DashboardScreen( // top level destination, the bottom bar is visible
    ...
) {
    Scaffold { innerPadding ->
        Box(
            modifier = Modifier
                .padding(innerPadding)
                .consumeWindowInsets(innerPadding)
                .padding(WindowInsets.navigationBars.asPaddingValues())
                .navigationBarsPadding()
                .fillMaxSize()
        ) {
            // screen content
        }
    }   
}

Right now the only solution I can use is to add additional custom bottom bar padding for each top level destination screen's:

@Composable
fun DashboardScreen( // top level destination, the bottom bar is visible
    ...
) {
    Scaffold { innerPadding ->
        Column(
            modifier = Modifier
                .padding(innerPadding)
                .consumeWindowInsets(innerPadding)
                .fillMaxSize()
                .verticalScroll(rememberScrollState())
        ) {
            
            // Screen Content
            
            Spacer(modifier = Modifier.height(BottomBarContainerHeight))
        }
    }
}

BottomBarContainerHeight:

val BottomBarContainerHeight = 80.0.dp // Material3's NavigationBar's height

It's ugly but at least I don't have issues with transition animations and scroll right now because NavHost's size is always the same

Would be grateful if somebody would show a better approach

Mousebird answered 18/5, 2023 at 19:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.