Search code examples
androidandroid-jetpack-composeandroid-jetpack-compose-material3

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


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.


Solution

  • 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.