Detecting if the Android keyboard is visible or hidden in Full-Screen mode

Anton Savinov
4 min readNov 24, 2019

In this article, I would like to share my experience with you about one of a problem with which I faced on one of my projects. The problem was about how to detect the keyboard opens and closes.

I’m sure some Android developers will be surprised at this one because a lot of corresponding topics are on the Internet. For instance: https://stackoverflow.com/questions/4745988/how-do-i-detect-if-software-keyboard-is-visible-on-android-device or https://stackoverflow.com/questions/2150078/how-to-check-visibility-of-software-keyboard-in-android. In a word these topics tell us how to detect the keyboard using onGlobalLayoutListener. Let’s take a look at one of them.

public static void setKeyboardVisibilityListener(Activity activity, KeyboardVisibilityListener keyboardVisibilityListener) {
View contentView = activity.findViewById(android.R.id.content);
contentView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
private int mPreviousHeight;
@Override
public void onGlobalLayout() {
int newHeight = contentView.getHeight();
if (mPreviousHeight != 0) {
if (mPreviousHeight > newHeight) {
// Height decreased: keyboard was shown
keyboardVisibilityListener.onKeyboardVisibilityChanged(true);
} else if (mPreviousHeight < newHeight) {
// Height increased: keyboard was hidden
keyboardVisibilityListener.onKeyboardVisibilityChanged(false);
} else {
// No change
}
}
mPreviousHeight = newHeight;
}
});
}

The author of the current solution tries to handle the keyboard appearing/disappearing based on content size. Of course, this approach works and it may be applied as the solution… But unlikely for my case.

I would like to tell you a little bit about my problem. Our application works in Full Screen mode i.e. without the navigation bar. To achieve such effect we use:

getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);

Let’s put a call of the method setKeyboardVisibilityListener in Activity. The callback onKeyboardVisibilityChanged() will return true if the keyboard is visible. At this moment I had to process some methods. Moment of truth came when I was to show something for the user. I used BottomSheetDialog to allow the user to interact with the app and provide a choice. I was surprised when BottomSheetDialog appeared and the method onKeyboardVisibilityChanged(true) was invoked. So, it was not my way and I started managing this issue to figure out what’s the trouble?

First of all, I visited the best site among Android developers. I found out method OnGlobalLayoutListener will be invoked if the navigation bar is appeared/dissapeared.

Then, I learned InputMethodManager to discover something related to input visibility. It seems, there is one thing:

/**
* Return true if the currently served view is accepting full text edits.
* If false, it has no input connection, so can only handle raw key events.
*/
public boolean isAcceptingText();

The description of this method told me I’m in the right way and may be useful to manage my problem. So I refactored the initial approach:

if (mPreviousHeight < newHeight) {
// In this place keyboard is hidden
// but navigation bar is appeared
// will hide it as well
if (mIsKeyboardVisible) {
mIsKeyboardVisible = false;
hideNavigationBar();
if (listener != null) {
listener.onKeyboardHidden();
}
} else if (mPreviousHeight > newHeight) {
// This block will be called when navigation bar is appeared
// There are two cases:
// 1. When something modal view (like dialog) is appeared
// 2. When keyboard is appeared
// Will ask InputMethodManager.isAcceptingText()
// to detect if keyboard accepred text or not.
InputMethodManager imm = (InputMethodManager) mContentView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
boolean isAcceptingText = imm.isAcceptingText();
if (isAcceptingText) {
mIsKeyboardVisible = true;
}
if (mIsKeyboardVisible) {
if (listener != null) {
listener.onKeyboardVisible();
}
}
}
}

I made sure when the dialog was appeared then property isAcceptingText took false. In the case of the keyboard, the last one was true. So it was a positive result.

Finally, I saved a positive state of isAcceptingText. It helped me to determine exactly the keyboard was hidden. I tested this solution and, you know, it works as it was expected.

So it was a reason to share this story with you, devs. Perhaps, it will be useful for someone else who works with Full-Screen mode.

I added link to my public repo with prototype of my solution.

Good luck!

--

--