Search code examples
android-jetpack-composewindowinsetsjetpack-compose-accompanist

Show keyboard over Scaffold's bottomBar in Jetpack Compose and apply proper inset paddings


I'm using Scaffold for my main screen with a fixed bottomBar that is visible in every screen of the app, and I'm applying the innerPadding of the Scaffold to its content.

I want the keyboard to appear over the bottomBar, and for that I'm applying the imePadding() only to the Scaffold's content.

However, when the keyboard is opened, both the Scaffold's innerPading and imePadding() are applied to the contents padding.

I've tried to go through the Accompanist Insets migration, but no lucky.

Is there anyway that I can prevent it and apply only one or the other?

Here is a piece of my code:

Scaffold(
    topBar = { },
    bottomBar = { },
    modifier = Modifier
        .systemBarsPadding()
) { innerPadding ->
    Content(
        modifier = Modifier
            .padding(innerPadding)
            .imePadding()
    )
}

And this is the result:

enter image description here

With the now, deprecated, Accompanist Insets, I was using the following solution:

val isImeVisible = LocalWindowInsets.current.ime.isVisible
val contentPadding = remember(isImeVisible) {
    if (isImeVisible) PaddingValues(top = innerPadding.calculateTopPadding()) else innerPadding
}

Solution

  • Since 1.4.0 you can use system WindowInsets.isImeVisible. For 1.3.0 see answer below:

    According to Accompanist Insets migration, LocalWindowInsets.current.ime should be replaced with WindowInsets.ime.

    It doesn't have isVisible for now, until this bug is fixed. Here's how I've re-created it for now:

    val WindowInsets.Companion.isImeVisible: Boolean
        @Composable
        get() {
            val density = LocalDensity.current
            val ime = this.ime
            return remember {
                derivedStateOf {
                    ime.getBottom(density) > 0
                }
            }.value
        }
    

    Usage:

    val isImeVisible = WindowInsets.isImeVisible
    

    This should work with your old remember(isImeVisible) code.