How can I detect keyboard opening and closing in jetpack compose?

Update

With the new WindowInsets API, it gets easier

First, to return the correct values, you need to set:

WindowCompat.setDecorFitsSystemWindows(window, false)

Then to use Keyboard as a state:

@Composable
fun keyboardAsState(): State<Boolean> {
    val isImeVisible = WindowInsets.ime.getBottom(LocalDensity.current) > 0
    return rememberUpdatedState(isImeVisible)
}

use example:

val isKeyboardOpen by keyboardAsState() // true or false

ps: I’ve tried to use WindowInsets.isImeVisible, but it returns true in the first call.


Without an experimental API

if you want with the statement, I found this solution:

enum class Keyboard {
    Opened, Closed
}

@Composable
fun keyboardAsState(): State<Keyboard> {
    val keyboardState = remember { mutableStateOf(Keyboard.Closed) }
    val view = LocalView.current
    DisposableEffect(view) {
        val onGlobalListener = ViewTreeObserver.OnGlobalLayoutListener {
            val rect = Rect()
            view.getWindowVisibleDisplayFrame(rect)
            val screenHeight = view.rootView.height
            val keypadHeight = screenHeight - rect.bottom
            keyboardState.value = if (keypadHeight > screenHeight * 0.15) {
                Keyboard.Opened
            } else {
                Keyboard.Closed
            }
        }
        view.viewTreeObserver.addOnGlobalLayoutListener(onGlobalListener)

        onDispose {
            view.viewTreeObserver.removeOnGlobalLayoutListener(onGlobalListener)
        }
    }

    return keyboardState
}

and to detect/check the value you’ll only need this:

val isKeyboardOpen by keyboardAsState() // Keyboard.Opened or Keyboard.Closed 

Leave a Comment