Your app is coming great!
In this episode you’ll use: DecorView, ViewTreeObserver, WindowInsets. API’s to implement a new feature.
Reading the keyboard height.
Until now there was no direct API to get the keyboard height. The best solution was to retrieve the window display frame and subtract its bottom value with the root view height.
val rect = Rect()
val decorView = requireActivity().window.decorView
val root: View = decorView.findViewById(android.R.id.content)
decorView.getWindowVisibleDisplayFrame(rect)
val keyboardHeight = root.rootView.height - rect.bottom
These fields correspond to these areas on the screen.
If the view is still being constructed, this value can be 0, so typically this logic is added to the OnGlobalLayoutListener:
val decorView = requireActivity().window.decorView
val root: View = decorView.findViewById(android.R.id.content)
root.viewTreeObserver.addOnGlobalLayoutListener {
val rect = Rect()
decorView.getWindowVisibleDisplayFrame(rect)
val keyboardHeight = root.rootView.height - rect.bottom
}
With this it’s possible to know the keyboard height when it’s opened. However, if it’s closed this logic is not 100% correct, since its value is not going to be 0, but instead a value that corresponds to the sum of the status and navigation bar height.
If this logic is used to know if a keyboard is open or closed, typically, a threshold is added to discard any value under 200dp.
private const val THRESHOLD = 200
val decorView = requireActivity().window.decorView
val root: View = decorView.findViewById(android.R.id.content)
root.viewTreeObserver.addOnGlobalLayoutListener {
val rect = Rect()
decorView.getWindowVisibleDisplayFrame(rect)
val keyboardHeight = root.rootView.height - rect.bottom
if (keyboardHeight < THRESHOLD) {
Toast.makeText(context, "Keyboard open!", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(context, "Keyboard closed!", Toast.LENGTH_SHORT).show()
}
}
Now with WindowInsets and the new keyboard features launched you can easily call:
view?.rootWindowInsets?.getInsets(WindowInsetsCompat.Type.ime())?.bottom
If the keyboard is visible this call will return its height, if not the value will be 0.
You can use the OnApplyWindowInsetsListener to get the updated value of the keyboard height, depending on if it’s opened or closed.
ViewCompat.setOnApplyWindowInsetsListener(requireView()) { v, insets ->
val height = view?.rootWindowInsets?.getInsets(WindowInsetsCompat.Type.ime())?.bottom
insets!!
}
That’s it! Yes, it’s really simple to read the keyboard height. Now that the app is open, don’t forget to add the episode name to the list: 03: Read the Keyboard Height.
See you in the next episode!