Notes: 02. Read the Keyboard Visibility
It’s time to dive in and start making some changes.
In this episode you’ll use: Focus, InputMethodManager and WindowInsetsController
In this episode you’re going to develop two features: when the app is launched the keyboard will automatically open? Tapping in the list will close the keyboard.
This is how the app currently looks.
Until now, if you want to close the keyboard manually you’ll need to either call:
binding.etContent.clearFocus() That internally removes the focus from the selected view. If this is an input view that triggered the keyboard to open, clearing its focus will close it.
InputMethodManager
val imm = requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(binding.etContent.windowToken, InputMethodManager.SHOW_FORCED)
Which uses the hideSoftInputFromWindow to force the keyboard to close.
-
WindowInsetsController
view?.windowInsetsController?.hide(WindowInsetsCompat.Type.ime())
Calling hide along with the IME type to force the keyboard to close. If instead, you want the keyboard to open, you can use the opposite calls:
binding.etContent.requestFocus() That internally selects this view as the one that’s currently focused, opening the keyboard
-
InputMethodManager
val imm = requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(binding.etContent, InputMethodManager.SHOW_FORCED)
Which uses the showSoftInput to force the keyboard to open.
-
WindowInsetsController
view?.windowInsetsController?.show(WindowInsetsCompat.Type.ime())
Calling show along with the IME type to force the keyboard to open. Using the WindowInsetsController API is also possible to have a direct call to know if the keyboard is visible or not, for that call:
view?.rootWindowInsets?.isVisible(WindowInsetsCompat.Type.ime())
Let’s start by loading the Starter project with Android Studio and open MainFragment.kt file. You’ve seen that there are different solutions to implement these features: by requesting focus, with InputMethodManager or now, via WindowInsets.
In this first feature, you’re going to use the first one. Search for the TextChangedListener inside the setupUiComponents method and after this code block add:
binding.etContent.requestFocus()
Compile and run the app. In the next launch, the keyboard will automatically open. The next feature is to close the keyboard if it’s open and the user touches outside the input field. Open RwCompatActions.kt and add this new method to the interface:
fun closeKeyboard(view: View)
In Android 11, there’s now a direct API to know if the keyboard is open or not. You’re going to use it on RwCompat11.kt file.
After the animateKeyboardDisplay function add closeKeyboard:
@RequiresApi(Build.VERSION_CODES.R)
fun closeKeyboard(view: View) {
if (view.rootWindowInsets?.isVisible(WindowInsetsCompat.Type.ime()) == true) {
view.windowInsetsController?.hide(WindowInsetsCompat.Type.ime())
}
}
Before calling hide you’re checking if the keyboard is first visible. For that, it’s necessary to access the rootWindowInsets which contains this logic.
If the keyboard is not open, the value of rootWindowInsets is going to be null, so you’ll need to check if the result is true or not. Now open RWCompat10 and add the closeKeyboard method:
fun closeKeyboard(view: View) {
view.clearFocus()
}
The keyboard is closed if view currently contains the main focus. Both implementations are now done. It’s necessary to open RWCompat.kt and implement the newly created method on RWCompatActions interface.
Press alt+enter to automatically create the new method. Depending on the current Android version, the system will call rwCompat11.closeKeyboard(view) or rwCompat10.closeKeyboard(view).
override fun closeKeyboard(view: View) {
if (isAtLeastAndroid11()) {
rwCompat11.closeKeyboard(view)
} else {
rwCompat10.closeKeyboard(view)
}
}
Finally, open once again MainFragment.kt file and this time look for binding.rvContent.apply. This is where the RecyclerView is being set. Add a touch listener event which will be responsible to call the newly added logic:
setOnTouchListener { _, _ ->
rwCompat.closeKeyboard(binding.etContent)
false
}
Since the parameters aren’t being used, you can omit them.
That’s it! Yes, it’s really simple to read the keyboard visibility and open/close it. Let’s compile and run the app to try out this feature. Now that the app is open, don’t forget to add the episode name to the list: 02: Read the Keyboard Visibility.
See you in the next episode!