How to Check Visibility of Software Keyboard in Android

How do I detect if software keyboard is visible on Android Device or not?

There is no direct way - see http://groups.google.com/group/android-platform/browse_thread/thread/1728f26f2334c060/5e4910f0d9eb898a where Dianne Hackborn from the Android team has replied. However, you can detect it indirectly by checking if the window size changed in #onMeasure. See How to check visibility of software keyboard in Android?.

How to check visibility of software keyboard in Android?

NEW ANSWER added Jan 25th 2012

Since writing the below answer, someone clued me in to the existence of ViewTreeObserver and friends, APIs which have been lurking in the SDK since version 1.

Rather than requiring a custom Layout type, a much simpler solution is to give your activity's root view a known ID, say @+id/activityRoot, hook a GlobalLayoutListener into the ViewTreeObserver, and from there calculate the size diff between your activity's view root and the window size:

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
if (heightDiff > dpToPx(this, 200)) { // if more than 200 dp, it's probably a keyboard...
// ... do something here
}
}
});

Using a utility such as:

public static float dpToPx(Context context, float valueInDp) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, metrics);
}

Easy!

Note:
Your application must set this flag in Android Manifest android:windowSoftInputMode="adjustResize" otherwise above solution will not work.

ORIGINAL ANSWER

Yes it's possible, but it's far harder than it ought to be.

If I need to care about when the keyboard appears and disappears (which is quite often) then what I do is customize my top-level layout class into one which overrides onMeasure(). The basic logic is that if the layout finds itself filling significantly less than the total area of the window, then a soft keyboard is probably showing.

import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.LinearLayout;

/*
* LinearLayoutThatDetectsSoftKeyboard - a variant of LinearLayout that can detect when
* the soft keyboard is shown and hidden (something Android can't tell you, weirdly).
*/

public class LinearLayoutThatDetectsSoftKeyboard extends LinearLayout {

public LinearLayoutThatDetectsSoftKeyboard(Context context, AttributeSet attrs) {
super(context, attrs);
}

public interface Listener {
public void onSoftKeyboardShown(boolean isShowing);
}
private Listener listener;
public void setListener(Listener listener) {
this.listener = listener;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = MeasureSpec.getSize(heightMeasureSpec);
Activity activity = (Activity)getContext();
Rect rect = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
int statusBarHeight = rect.top;
int screenHeight = activity.getWindowManager().getDefaultDisplay().getHeight();
int diff = (screenHeight - statusBarHeight) - height;
if (listener != null) {
listener.onSoftKeyboardShown(diff>128); // assume all soft keyboards are at least 128 pixels high
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

}

Then in your Activity class...

public class MyActivity extends Activity implements LinearLayoutThatDetectsSoftKeyboard.Listener {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
LinearLayoutThatDetectsSoftKeyboard mainLayout = (LinearLayoutThatDetectsSoftKeyboard)findViewById(R.id.main);
mainLayout.setListener(this);
...
}


@Override
public void onSoftKeyboardShown(boolean isShowing) {
// do whatever you need to do here
}

...
}

Is there a way of detecting whether or not the softkeyboard is open in Android?

We have currently Android N now and still no direct ways to detect if keyboard is opened or not. There're only work around solutions available like the ones checking the screen size. However there're not fullproof and some times give false signals for example on screen rotation or going into multi-window mode on Android N.

Soft keyboard open and close listener in an activity in Android

This only works when android:windowSoftInputMode of your activity is set to adjustResize in the manifest. You can use a layout listener to see if the root layout of your activity is resized by the keyboard.

I use something like the following base class for my activities:

public class BaseActivity extends Activity {
private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = rootLayout.getRootView().getHeight() - rootLayout.getHeight();
int contentViewTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();

LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(BaseActivity.this);

if(heightDiff <= contentViewTop){
onHideKeyboard();

Intent intent = new Intent("KeyboardWillHide");
broadcastManager.sendBroadcast(intent);
} else {
int keyboardHeight = heightDiff - contentViewTop;
onShowKeyboard(keyboardHeight);

Intent intent = new Intent("KeyboardWillShow");
intent.putExtra("KeyboardHeight", keyboardHeight);
broadcastManager.sendBroadcast(intent);
}
}
};

private boolean keyboardListenersAttached = false;
private ViewGroup rootLayout;

protected void onShowKeyboard(int keyboardHeight) {}
protected void onHideKeyboard() {}

protected void attachKeyboardListeners() {
if (keyboardListenersAttached) {
return;
}

rootLayout = (ViewGroup) findViewById(R.id.rootLayout);
rootLayout.getViewTreeObserver().addOnGlobalLayoutListener(keyboardLayoutListener);

keyboardListenersAttached = true;
}

@Override
protected void onDestroy() {
super.onDestroy();

if (keyboardListenersAttached) {
rootLayout.getViewTreeObserver().removeGlobalOnLayoutListener(keyboardLayoutListener);
}
}
}

The following example activity uses this to hide a view when the keyboard is shown and show it again when the keyboard is hidden.

The xml layout:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<ScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
>

<!-- omitted for brevity -->

</ScrollView>

<LinearLayout android:id="@+id/bottomContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>

<!-- omitted for brevity -->

</LinearLayout>

</LinearLayout>

And the activity:

public class TestActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_activity);

attachKeyboardListeners();
}

@Override
protected void onShowKeyboard(int keyboardHeight) {
// do things when keyboard is shown
bottomContainer.setVisibility(View.GONE);
}

@Override
protected void onHideKeyboard() {
// do things when keyboard is hidden
bottomContainer.setVisibility(View.VISIBLE);
}
}

Is there an android keyboard listener?

According to the accepted answer here, "You can use a layout listener to see if the root layout of your activity is resized by the keyboard.": Soft keyboard open and close listener in an activity in Android



Related Topics



Leave a reply



Submit