Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check visibility of software keyboard in Android?

I need to do a very simple thing - find out if the software keyboard is shown. Is this possible in Android?

like image 734
fhucho Avatar asked Jan 27 '10 20:01

fhucho


People also ask

How do I know if my keyboard is visible on Android?

Android provides no direct way to determine if the keyboard is open, so we have to get a little creative. The View class has a handy method called getWindowVisibleDisplayFrame from which we can retrieve a rectangle which contains the portion of the view visible to the user.

How do I make my keyboard invisible on Android?

You can force Android to hide the virtual keyboard using the InputMethodManager, calling hideSoftInputFromWindow, passing in the token of the window containing your edit field. This will force the keyboard to be hidden in all situations.

What is soft keyboard in Android?

The soft keyboard (also called the onscreen keyboard) is the main input method on Android devices, and almost every Android developer needs to work with this component at some point.


2 Answers

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     }      ... } 
like image 99
Reuben Scratton Avatar answered Oct 11 '22 08:10

Reuben Scratton


So hopefully this helps someone out.

The new answer that Reuben Scratton gave is great and really efficient, but it really only works if you set your windowSoftInputMode to adjustResize. If you set it to adjustPan, it's still not possible to detect whether or not the keyboard is visible using his code snippet. To work around this, I made this tiny modification to the code above.

final View activityRootView = findViewById(R.id.activityRoot); activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() {     Rect r = new Rect();     //r will be populated with the coordinates of your view that area still visible.     activityRootView.getWindowVisibleDisplayFrame(r);         int heightDiff = activityRootView.getRootView().getHeight() - r.height();     if (heightDiff > 0.25*activityRootView.getRootView().getHeight()) { // if more than 25% of the screen, its probably a keyboard...         ... do something here     }  } });  
like image 30
Kachi Avatar answered Oct 11 '22 09:10

Kachi