This is solution that is composed of code from SO and my enhancement to support various API levels.
Inspired by SO post
http://stackoverflow.com/questions/2150078/how-to-check-visibility-of-software-keyboard-in-android
Updated 1/24/2017
Updated 15 Apr. 2017
I hope, this solution is final.
Preparation class:
package my.package.utils;
import android.graphics.Rect;
import android.os.Build;
import android.view.View;
import android.view.ViewTreeObserver;
import java.util.LinkedList;
import java.util.List;
public class SoftKeyboardStateWatcher
implements ViewTreeObserver.OnGlobalLayoutListener {
public void onStart() {
isSoftKeyboardOpened = false;
}
public interface SoftKeyboardStateListener {
void onSoftKeyboardOpened(int keyboardHeightInPx);
void onSoftKeyboardClosed();
}
private SoftKeyboardStateListener listener;
private final View activityRootView;
private boolean isSoftKeyboardOpened;
private int resize;
private int mKeyboardHeight;
public SoftKeyboardStateWatcher(
View activityRootView,
SoftKeyboardStateListener listener
) {
this(activityRootView, false);
this.listener = listener;
}
private SoftKeyboardStateWatcher(
View activityRootView,
boolean isSoftKeyboardOpened
) {
this.activityRootView = activityRootView;
this.isSoftKeyboardOpened = isSoftKeyboardOpened;
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(this);
}
@Override public void onGlobalLayout() {
Rect r = new Rect();
activityRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
int correction = r.top;
if (!isSoftKeyboardOpened && heightDiff > correction &&
heightDiff > getStatusBarHeight() + getNavBarHeight()) {
isSoftKeyboardOpened = true;
notifyOnSoftKeyboardOpened(heightDiff, correction);
} else {
if (isSoftKeyboardOpened && heightDiff <= correction) {
isSoftKeyboardOpened = false;
notifyOnSoftKeyboardClosed();
}else{
if (!isSoftKeyboardOpened) return;
if (mKeyboardHeight == heightDiff - correction) return;
//Keyboard height has changed
}
}
}
private void notifyOnSoftKeyboardOpened(int keyboardHeightInPx, int correction) {
if (listener == null) return;
mKeyboardHeight = keyboardHeightInPx - correction;
listener.onSoftKeyboardOpened(keyboardHeightInPx);
}
private void notifyOnSoftKeyboardClosed() {
if (listener == null) return;
listener.onSoftKeyboardClosed();
}
public void removeSoftKeyboardStateListener() {
listener = null;
}
private int getStatusBarHeight() {
int result = 0;
Resources resources = activityRootView.getResources();
int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = resources.getDimensionPixelSize(resourceId);
}
return result;
}
private int getNavBarHeight() {
Resources resources = activityRootView.getResources();
int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
return resources.getDimensionPixelSize(resourceId);
}
return 0;
}
public boolean isSoftKeyboardOpened() {
return isSoftKeyboardOpened;
}
}
The next step:
Your activity must implement
SoftKeyboardStateWatcher.SoftKeyboardStateListener
Declare in your activity
protected SoftKeyboardStateWatcher mSoftKeyboardStateWatcher;
And run following code in onCreate:
int rootId = getRootId();//here you must supply root View id
View root;
if (rootId == 0 || (root = findViewById(rootId)) == null) return;
mSoftKeyboardStateWatcher = new SoftKeyboardStateWatcher(root);
mSoftKeyboardStateWatcher.addSoftKeyboardStateListener(his);
Now you have these methods:
@Override
public void onSoftKeyboardOpened(int keyboardHeightInPx) {
}
@Override
public void onSoftKeyboardClosed() {
}
Also do not forget to remove listener:
@Override
public void onDestroy() {
if (mSoftKeyboardStateWatcher != null)
mSoftKeyboardStateWatcher.removeSoftKeyboardStateListener(this);
super.onDestroy();
}