How to avoid Modal Bottom Sheet overlap with System Navigation Icons in Android

2.1k views Asked by At

The Material3 Modal Bottom Sheet is currently overlapping with the system navigation buttons. Is there a way to avoid this overlap with the system navigation buttons.

This is the code that I am using for showing modal bottom sheet


@Composable
fun TestScreen() {
    var sheetOpened by mutableStateOf(false)

    Scaffold() {
       Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
         Button(onClick = { sheetOpened = true }){
              Text("Open Bottom Sheet")  
          }
       }
    }

    if(sheetOpened){
        ModalBottomSheet(onDismissRequest = {sheetOpened = false}){
            Box(Modifier.fillMaxWidth().height(500.dp).background(Color.RED))
        }
    }
}

enter image description here

Tried putting the Modal Bottom Sheet inside the Scaffold, but that does not work either.

5

There are 5 answers

3
Saliou Seck On BEST ANSWER

To address this issue, inform Jetpack Compose that you'll be handling insets manually. Add the following code to your MainActivity:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Manually handle all the insets
        WindowCompat.setDecorFitsSystemWindows(window, false)

        setContent {
            ApplicationTheme {
                // Your Composables
            }
        }
    }
}

Next, calculate the BottomPadding of your BottomModalSheet using the following approach:

val bottomPadding = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()

Apply this in your BetterModalBottomSheet composable as shown in the sample code:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BetterModalBottomSheet(
    ...
) {
    val bottomPadding = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()

    if (showSheet) {
        ModalBottomSheet(
            ...
        ) {
            Column(modifier = Modifier.padding(bottom = bottomPadding)) {
                // Your content
            }
        }
    }
}

For additional details, refer to this post.

1
tim.paetz On

For me, I had called the androidx.activity.enableEdgeToEdge.enableEdgeToEdge() function in my MainActivity. This causes your UI to draw behind the bottom navigation and system bar per the documentation found here: https://developer.android.com/develop/ui/views/layout/edge-to-edge

Deleting the enableEdgeToEdge() call fixed it for me.

Hope this helps.

0
pieljo On

I figured out the height of the Navigationbar in my MainActivity

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val view = window.decorView
    val insets = ViewCompat.getRootWindowInsets(view)
    val navigationBarHeight = insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom }

added a Parameter to my Screen

MyScreen(
    navigationHeight = navigationHeight
    ...
)

and then added the navigatoinBarHeight into my BottomSheet as a WindowBottomInset.

ModalBottomSheet(
      windowInsets = WindowInsets(bottom = navigatoinBarHeight)
      ...
){ ... }

the close animation is not a 100% percent smooth but other then that is works perfectly.

0
maatik5 On

My solution is to add a Spacer at the bottom of ModalBottomSheet content.

Spacer(
    Modifier.windowInsetsBottomHeight(
        WindowInsets.navigationBarsIgnoringVisibility
    )
)
0
Randy Sugianto 'Yuku' On

The easiest so far...

ModalBottomSheet(onDismissRequest = { ... }) {
    Column(
        modifier = Modifier.navigationBarsPadding(),
    ) {
        // bottom sheet content
    }
}