How to capture the "virtual keyboard show/hide" event in Android? How to capture the "virtual keyboard show/hide" event in Android? android android

How to capture the "virtual keyboard show/hide" event in Android?


2020 Update

This is now possible:

On Android 11, you can do

view.setWindowInsetsAnimationCallback(object : WindowInsetsAnimation.Callback {    override fun onEnd(animation: WindowInsetsAnimation) {        super.onEnd(animation)        val showingKeyboard = view.rootWindowInsets.isVisible(WindowInsets.Type.ime())        // now use the boolean for something    }})

You can also listen to the animation of showing/hiding the keyboard and do a corresponding transition.

I recommend reading Android 11 preview and the corresponding documentation

Before Android 11

However, this work has not been made available in a Compat version, so you need to resort to hacks.

You can get the window insets and if the bottom insets are bigger than some value you find to be reasonably good (by experimentation), you can consider that to be showing the keyboard. This is not great and can fail in some cases, but there is no framework support for that.

This is a good answer on this exact question https://stackoverflow.com/a/36259261/372076. Alternatively, here's a page giving some different approaches to achieve this pre Android 11:

https://developer.salesforce.com/docs/atlas.en-us.noversion.service_sdk_android.meta/service_sdk_android/android_detecting_keyboard.htm


Note

This solution will not work for soft keyboards andonConfigurationChanged will not be called for soft (virtual)keyboards.


You've got to handle configuration changes yourself.

http://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange

Sample:

// from the link above@Overridepublic void onConfigurationChanged(Configuration newConfig) {    super.onConfigurationChanged(newConfig);        // Checks whether a hardware keyboard is available    if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {        Toast.makeText(this, "keyboard visible", Toast.LENGTH_SHORT).show();    } else if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {        Toast.makeText(this, "keyboard hidden", Toast.LENGTH_SHORT).show();    }}

Then just change the visibility of some views, update a field, and change your layout file.


This may not be the most effective solution. But this worked for me every time... I call this function where ever i need to listen to the softKeyboard.

boolean isOpened = false;public void setListenerToRootView() {    final View activityRootView = getWindow().getDecorView().findViewById(android.R.id.content);    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {        @Override        public void onGlobalLayout() {            int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();            if (heightDiff > 100) { // 99% of the time the height diff will be due to a keyboard.                Toast.makeText(getApplicationContext(), "Gotcha!!! softKeyboardup", 0).show();                if (isOpened == false) {                    //Do two things, make the view top visible and the editText smaller                }                isOpened = true;            } else if (isOpened == true) {                Toast.makeText(getApplicationContext(), "softkeyborad Down!!!", 0).show();                isOpened = false;            }        }    });}

Note: This approach will cause issues if the user uses a floating keyboard.


I did this way:

Add OnKeyboardVisibilityListener interface.

public interface OnKeyboardVisibilityListener {    void onVisibilityChanged(boolean visible);}

HomeActivity.java:

public class HomeActivity extends Activity implements OnKeyboardVisibilityListener {@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_sign_up);    // Other stuff...    setKeyboardVisibilityListener(this);}private void setKeyboardVisibilityListener(final OnKeyboardVisibilityListener onKeyboardVisibilityListener) {    final View parentView = ((ViewGroup) findViewById(android.R.id.content)).getChildAt(0);    parentView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {        private boolean alreadyOpen;        private final int defaultKeyboardHeightDP = 100;        private final int EstimatedKeyboardDP = defaultKeyboardHeightDP + (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? 48 : 0);        private final Rect rect = new Rect();        @Override        public void onGlobalLayout() {            int estimatedKeyboardHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, EstimatedKeyboardDP, parentView.getResources().getDisplayMetrics());            parentView.getWindowVisibleDisplayFrame(rect);            int heightDiff = parentView.getRootView().getHeight() - (rect.bottom - rect.top);            boolean isShown = heightDiff >= estimatedKeyboardHeight;            if (isShown == alreadyOpen) {                Log.i("Keyboard state", "Ignoring global layout change...");                return;            }            alreadyOpen = isShown;            onKeyboardVisibilityListener.onVisibilityChanged(isShown);        }    });}@Overridepublic void onVisibilityChanged(boolean visible) {    Toast.makeText(HomeActivity.this, visible ? "Keyboard is active" : "Keyboard is Inactive", Toast.LENGTH_SHORT).show();  }}

Hope this would help you.