¿Cómo verificar la visibilidad del keyboard de software en Android?

Necesito hacer algo muy simple: averigüe si se muestra el keyboard del software. ¿Es esto posible en Android?

NUEVA RESPUESTA añadida el 25 de enero de 2012

Desde que escribí la respuesta a continuación, alguien me dio a conocer la existencia de ViewTreeObserver y amigos, API que han estado al acecho en el SDK desde la versión 1.

En lugar de requerir un tipo de layout personalizado, una solución mucho más simple es dar una identificación conocida a la vista raíz de su actividad, digamos @+id/activityRoot , enganchar un GlobalLayoutListener en ViewTreeObserver, y desde allí calcular la diferencia de tamaño entre la raíz de la vista de su actividad y el tamaño de la window:

 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 } } }); 

Usando una utilidad como:

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

¡Fácil!

Nota: Su aplicación debe establecer este indicador en Android Manifest android:windowSoftInputMode="adjustResize" contrario la solución anterior no funcionará.

RESPUESTA ORIGINAL

Sí, es posible, pero es mucho más difícil de lo que debería ser.

Si necesito preocuparme sobre cuándo aparece y desaparece el keyboard (lo cual es bastante frecuente), entonces lo que hago es personalizar mi class de layout de nivel superior en una que anule onMeasure() . La lógica básica es que si el layout se encuentra llenando significativamente less que el área total de la window, entonces probablemente se muestre un keyboard virtual.

 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); } } 

Luego en tu class de Actividad …

 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 } ... } 

Así que con suerte esto ayuda a alguien.

La nueva respuesta que dio Reuben Scratton es excelente y muy eficiente, pero realmente solo funciona si configuras tu windowSoftInputMode para ajustarResize. Si lo configura para ajustar Pan, aún no es posible detectar si el keyboard es visible usando su fragment de código. Para evitar esto, hice esta pequeña modificación al código anterior.

 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.bottom - r.top); if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard... ... do something here } } }); 

Perdón por la respuesta tardía, pero había creado una pequeña class de ayuda para manejar events de apertura / cierre con la notificación a oyentes y otras cosas útiles, puede ser que alguien lo encuentre útil:

 import android.graphics.Rect; import android.view.View; import android.view.ViewTreeObserver; import java.util.LinkedList; import java.util.List; public class SoftKeyboardStateWatcher implements ViewTreeObserver.OnGlobalLayoutListener { public interface SoftKeyboardStateListener { void onSoftKeyboardOpened(int keyboardHeightInPx); void onSoftKeyboardClosed(); } private final List<SoftKeyboardStateListener> listeners = new LinkedList<SoftKeyboardStateListener>(); private final View activityRootView; private int lastSoftKeyboardHeightInPx; private boolean isSoftKeyboardOpened; public SoftKeyboardStateWatcher(View activityRootView) { this(activityRootView, false); } public SoftKeyboardStateWatcher(View activityRootView, boolean isSoftKeyboardOpened) { this.activityRootView = activityRootView; this.isSoftKeyboardOpened = isSoftKeyboardOpened; activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(this); } @Override public void onGlobalLayout() { final Rect r = new Rect(); //r will be populated with the coordinates of your view that area still visible. activityRootView.getWindowVisibleDisplayFrame(r); final int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top); if (!isSoftKeyboardOpened && heightDiff > 100) { // if more than 100 pixels, its probably a keyboard... isSoftKeyboardOpened = true; notifyOnSoftKeyboardOpened(heightDiff); } else if (isSoftKeyboardOpened && heightDiff < 100) { isSoftKeyboardOpened = false; notifyOnSoftKeyboardClosed(); } } public void setIsSoftKeyboardOpened(boolean isSoftKeyboardOpened) { this.isSoftKeyboardOpened = isSoftKeyboardOpened; } public boolean isSoftKeyboardOpened() { return isSoftKeyboardOpened; } /** * Default value is zero {@code 0}. * * @return last saved keyboard height in px */ public int getLastSoftKeyboardHeightInPx() { return lastSoftKeyboardHeightInPx; } public void addSoftKeyboardStateListener(SoftKeyboardStateListener listener) { listeners.add(listener); } public void removeSoftKeyboardStateListener(SoftKeyboardStateListener listener) { listeners.remove(listener); } private void notifyOnSoftKeyboardOpened(int keyboardHeightInPx) { this.lastSoftKeyboardHeightInPx = keyboardHeightInPx; for (SoftKeyboardStateListener listener : listeners) { if (listener != null) { listener.onSoftKeyboardOpened(keyboardHeightInPx); } } } private void notifyOnSoftKeyboardClosed() { for (SoftKeyboardStateListener listener : listeners) { if (listener != null) { listener.onSoftKeyboardClosed(); } } } } 

Ejemplo de uso:

 final SoftKeyboardStateWatcher softKeyboardStateWatcher = new SoftKeyboardStateWatcher(findViewById(R.id.activity_main_layout); // Add listener softKeyboardStateWatcher.addSoftKeyboardStateListener(...); // then just handle callbacks 

Ha sido para siempre en términos de computadora, pero esta pregunta sigue siendo increíblemente relevante.

Así que tomé las respuestas anteriores y las he combinado y refinado un poco …

 public interface OnKeyboardVisibilityListener { void onVisibilityChanged(boolean visible); } public final void setKeyboardListener(final OnKeyboardVisibilityListener listener) { final View activityRootView = ((ViewGroup) getActivity().findViewById(android.R.id.content)).getChildAt(0); activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { private boolean wasOpened; private final int DefaultKeyboardDP = 100; // From @nathanielwolf answer... Lollipop includes button bar in the root. Add height of button bar (48dp) to maxDiff private final int EstimatedKeyboardDP = DefaultKeyboardDP + (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? 48 : 0); private final Rect r = new Rect(); @Override public void onGlobalLayout() { // Convert the dp to pixels. int estimatedKeyboardHeight = (int) TypedValue .applyDimension(TypedValue.COMPLEX_UNIT_DIP, EstimatedKeyboardDP, activityRootView.getResources().getDisplayMetrics()); // Conclude whether the keyboard is shown or not. activityRootView.getWindowVisibleDisplayFrame(r); int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top); boolean isShown = heightDiff >= estimatedKeyboardHeight; if (isShown == wasOpened) { Log.d("Keyboard state", "Ignoring global layout change..."); return; } wasOpened = isShown; listener.onVisibilityChanged(isShown); } }); } 

Funciona para mi 🙂

NOTA: Si observa que el DefaultKeyboardDP no se ajusta a su dispositivo, juegue con el valor y publique un comentario para que todos sepan cuál debería ser el valor … ¡con el time obtendremos el valor correcto para todos los dispositivos!

Algunas mejoras para evitar detectar erróneamente la visibilidad del keyboard virtual en dispositivos de alta densidad:

  1. El umbral de diferencia de altura debe definirse como 128 dp , no 128 píxeles .
    Consulte el documento de layout de Google sobre Métricas y cuadrícula , 48 dp es un tamaño cómodo para objects táctiles y 32 dp es mínimo para botones. El keyboard genérico debe include 4 filas de botones key, por lo que la altura mínima del keyboard debe ser: 32 dp * 4 = 128 dp , eso significa que el tamaño del umbral debe transferirse a píxeles multiplicando la densidad del dispositivo. Para dispositivos xxxhdpi (densidad 4), el umbral de altura del keyboard de software debe ser de 128 * 4 = 512 píxeles.

  2. Diferencia de altura entre la vista de la raíz y su área visible:
    altura de vista de raíz – altura de barra de estado – altura de marco visible = vista de raíz inferior – parte inferior de marco visible, ya que la altura de la barra de estado es igual a la parte superior del marco visible de la vista de raíz.

     private final String TAG = "TextEditor"; private TextView mTextEditor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_editor); mTextEditor = (TextView) findViewById(R.id.text_editor); mTextEditor.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { isKeyboardShown(mTextEditor.getRootView()); } }); } private boolean isKeyboardShown(View rootView) { /* 128dp = 32dp * 4, minimum button height 32dp and generic 4 rows soft keyboard */ final int SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD = 128; Rect r = new Rect(); rootView.getWindowVisibleDisplayFrame(r); DisplayMetrics dm = rootView.getResources().getDisplayMetrics(); /* heightDiff = rootView height - status bar height (r.top) - visible frame height (r.bottom - r.top) */ int heightDiff = rootView.getBottom() - r.bottom; /* Threshold size: dp to pixels, multiply with display density */ boolean isKeyboardShown = heightDiff > SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD * dm.density; Log.d(TAG, "isKeyboardShown ? " + isKeyboardShown + ", heightDiff:" + heightDiff + ", density:" + dm.density + "root view height:" + rootView.getHeight() + ", rect:" + r); return isKeyboardShown; } 

Utilicé un poco de time para resolver esto … Ejecuté CastExceptions, pero descubrí que puedes replace tu LinearLayout en el file layout.xml con el nombre de la class.

Me gusta esto:

 <?xml version="1.0" encoding="UTF-8"?> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/llMaster"> <com.ourshoppingnote.RelativeLayoutThatDetectsSoftKeyboard android:background="@drawable/metal_background" android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/rlMaster" > <LinearLayout android:layout_width="fill_parent" android:layout_height="1dip" android:background="@drawable/line"></LinearLayout> .... </com.ourshoppingnote.RelativeLayoutThatDetectsSoftKeyboard> </LinearLayout> 

De esa forma no se encontrará con ningún problema de lanzamiento.

… y si no quieres hacer esto en cada página, te recomiendo que uses "MasterPage en Android". Vea el enlace aquí: http://jnastase.alner.net/archive/2011/01/08/ldquomaster-pagesrdquo-in-android.aspx

Comprobar la altura de los elementos no es confiable porque algunos keyboards como WifiKeyboard tienen altura cero.

En su lugar, puede usar el resultado de callback de showSoftInput () y hideSoftInput () para verificar el estado del keyboard. Detalles completos y código de ejemplo en

http://www.ninthavenue.com.au/how-to-check-if-the-software-keyboard-is-shown-in-android

La idea es, si necesita ocultar su keyboard y verificar el estado de input suave al mismo time, use la siguiente solución:

 public boolean hideSoftInput() { InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE); return imm.hideSoftInputFromWindow(mViewPager.getWindowToken(), 0); } 

Este método devuelve verdadero si el keyboard se mostró antes de ocultarse.

En lugar de asumir la encoding de diferencia, hice algo como esto, ya que no tenía opciones de menu en mi aplicación.

 final View root= findViewById(R.id.myrootview); root.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { int heightDiff = root.getRootView().getHeight() - root.getHeight(); Rect rectgle= new Rect(); Window window= getWindow(); window.getDecorView().getWindowVisibleDisplayFrame(rectgle); int contentViewTop= window.findViewById(Window.ID_ANDROID_CONTENT).getTop(); if(heightDiff <= contentViewTop){ //Soft KeyBoard Hidden }else{ //Soft KeyBoard Shown } } }); 

Descubrí que una combinación del método de @Reuben_Scratton junto con el método de @ Yogesh parece funcionar mejor. La combinación de sus methods arrojaría algo como esto:

 final View activityRootView = findViewById(R.id.activityRoot); activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (getResources().getConfiguration().keyboardHidden == Configuration.KEYBOARDHIDDEN_NO) { // Check if keyboard is not hidden // ... do something here } } }); 

Puedes observar el hide del keyboard utilizando DecoView de la actividad.

 public final class SoftKeyboardUtil { public static final String TAG = "SoftKeyboardUtil"; public static void observeSoftKeyBoard(Activity activity , final OnSoftKeyBoardHideListener listener){ final View decorView = activity.getWindow().getDecorView(); decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { Rect rect = new Rect(); decorView.getWindowVisibleDisplayFrame(rect); int displayHight = rect.bottom - rect.top; int hight = decorView.getHeight(); boolean hide = (double)displayHight / hight > 0.8 ; if(Log.isLoggable(TAG, Log.DEBUG)){ Log.d(TAG ,"DecorView display hight = "+displayHight); Log.d(TAG ,"DecorView hight = "+ hight); Log.d(TAG, "softkeyboard visible = " + !hide); } listener.onSoftKeyBoardVisible(!hide); } }); } public interface OnSoftKeyBoardHideListener{ void onSoftKeyBoardVisible(boolean visible); } } 

Ninguna de estas soluciones funcionará para Lollipop como está. En Lollipop activityRootView.getRootView().getHeight() incluye la altura de la barra de botones, mientras que la medición de la vista no lo hace. He adaptado la mejor / más simple solución anterior para trabajar con Lollipop.

  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.bottom - r.top); Resources res = getResources(); // The status bar is 25dp, use 50dp for assurance float maxDiff = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, res.getDisplayMetrics()); //Lollipop includes button bar in the root. Add height of button bar (48dp) to maxDiff if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { float buttonBarHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48, res.getDisplayMetrics()); maxDiff += buttonBarHeight; } if (heightDiff > maxDiff) { // if more than 100 pixels, its probably a keyboard... ...do something here } } }); 

I used a slight variant of Reuban's answer, which proved to be more helpful in certain circumstances, especially with high resolution devices.

 final View activityRootView = findViewById(android.R.id.content); activityRootView.getViewTreeObserver().addOnGlobalLayoutListener( new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { int heightView = activityRootView.getHeight(); int widthView = activityRootView.getWidth(); if (1.0 * widthView / heightView > 3) { //Make changes for Keyboard not visible } else { //Make changes for keyboard visible } } }); 

It has been forever in terms of the computer but this question is still unbelievably relevant! So I've taken the above answers and have combined and refined them a bit…

 public interface OnKeyboardVisibilityListener { void onVisibilityChanged(boolean visible); } public final void setKeyboardListener(final OnKeyboardVisibilityListener listener) { final View activityRootView = ((ViewGroup) getActivity().findViewById(android.R.id.content)).getChildAt(0); activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { private boolean wasOpened; private final Rect r = new Rect(); @Override public void onGlobalLayout() { activityRootView.getWindowVisibleDisplayFrame(r); int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top); boolean isOpen = heightDiff > 100; if (isOpen == wasOpened) { logDebug("Ignoring global layout change..."); return; } wasOpened = isOpen; listener.onVisibilityChanged(isOpen); } }); } 

It works for me.

My answer is basically the same as Kachi's answer, but I wrapped it into a nice helper class to clean up the way it's used throughout my app.

 import android.app.Activity; import android.app.Fragment; import android.graphics.Rect; import android.view.View; import android.view.ViewTreeObserver.OnGlobalLayoutListener; /** * Detects Keyboard Status changes and fires events only once for each change */ public class KeyboardStatusDetector { KeyboardVisibilityListener visibilityListener; boolean keyboardVisible = false; public void registerFragment(Fragment f) { registerView(f.getView()); } public void registerActivity(Activity a) { registerView(a.getWindow().getDecorView().findViewById(android.R.id.content)); } public KeyboardStatusDetector registerView(final View v) { v.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { Rect r = new Rect(); v.getWindowVisibleDisplayFrame(r); int heightDiff = v.getRootView().getHeight() - (r.bottom - r.top); if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard... /** Check this variable to debounce layout events */ if(!keyboardVisible) { keyboardVisible = true; if(visibilityListener != null) visibilityListener.onVisibilityChanged(true); } } else { if(keyboardVisible) { keyboardVisible = false; if(visibilityListener != null) visibilityListener.onVisibilityChanged(false); } } } }); return this; } public KeyboardStatusDetector setVisibilityListener(KeyboardVisibilityListener listener) { visibilityListener = listener; return this; } public static interface KeyboardVisibilityListener { public void onVisibilityChanged(boolean keyboardVisible); } } 

You can use this to detect keyboard changes anywhere throughout the app like this:

  new KeyboardStatusDetector() .registerFragment(fragment) //register to a fragment .registerActivity(activity) //or register to an activity .registerView(view) //or register to a view .setVisibilityListener(new KeyboardVisibilityListener() { @Override public void onVisibilityChanged(boolean keyboardVisible) { if(keyboardVisible) { //Do stuff for keyboard visible }else { //Do stuff for keyboard hidden } } }); 

Note: only use one of the "register" calls. They all work the same and are only there for convenience

you can try this, work great for me:

 InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); if (imm.isAcceptingText()) { //Software Keyboard was shown.. } else { //Software Keyboard was not shown.. } 

I have just encountenetworking a bug while using most of the solutions above that suggest adding a fixed number.

S4 is has a high dpi which resulted in the navigation bar's height being 100px thus my app thinking that the keyboard is open all the time.

So with all the new high res phones being released i believe using a hard coded value is not a good idea for long term.

A better approach that i found after some testing on various screens and devices was to use percentage. Get the difference between decorView and ur app content and afterwards check what is the percentage of that difference. From the stats that i got, most nav bar(regardless of the size, resolution etc..) will take between 3% to 5% of the screen. Where as if the keyboard is open it was taking between 47% to 55% of the screen.

As a conclusion my solution was to check if the diff is more than 10% then i assume its a keyboard open.

I was having difficulty maintaining keyboard state when changing orientation of fragments within a viewpager. I'm not sure why, but it just seems to be wonky and acts differently from a standard Activity.

To maintain keyboard state in this case, first you should add android:windowSoftInputMode = "stateUnchanged" to your AndroidManifest.xml . You may notice, though, that this doesn't actually solve the entire problem — the keyboard didn't open for me if it was previously opened before orientation change. In all other cases, the behavior seemed to be correct.

Then, we need to implement one of the solutions mentioned here. The cleanest one I found was George Maisuradze's–use the boolean callback from hideSoftInputFromWindow:

 InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE); return imm.hideSoftInputFromWindow(mViewPager.getWindowToken(), 0); 

I stonetworking this value in my Fragment's onSaveInstanceState method and retrieved it onCreate . Then, I forcibly showed the keyboard in onCreateView if it had a value of true (it returns true if the keyboard is visible before actually hiding it prior to the Fragment destruction).

Try this:

 final View activityRootView = getWindow().getDecorView().getRootView(); activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.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.bottom - r.top); if (heightDiff < activityRootView.getRootView().getHeight() / 4 ) { // if more than 100 pixels, its probably a keyboard... // ... do something here ... \\ } } }); 

The InputMethodManager has information about the soft keyboard. You get it from an activity via:

 ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)) 

You might play around with that to see what it can tell you. You can use it to show or hide the soft input…

Here's my solution, and it works. Instead of looking for pixel size just check that the height of the content view has changed or not:

 // Scroll to the latest comment whenever the keyboard is shown commentsContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { private int oldHeight; @Override public void onGlobalLayout() { int newHeight = commentsContent.getMeasunetworkingHeight(); if (newHeight < oldHeight) { // Check for the keyboard showing in case the height difference // is a result of orientation change if (isSoftKeyboardShowing(CommentsActivity.this)) { // Keyboard is showing so scroll to the latest comment scrollToLatestComment(); } } oldHeight = newHeight; } }); public static boolean isSoftKeyboardShowing(Activity activity) { InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE); return inputMethodManager.isActive(); } 

Don't make any hard code. Best way is you have to resize your views while on Get Focus on EditText with KeyBord Show. You can do this adding resize property on activity into Manifest file using below code.

android:windowSoftInputMode="adjustResize"

There is a direct method to find this out. And, it does not require any Layout changes.
So, it works in immersive fullscreen mode, too.

The trick is that you try to hide or show the soft keyboard and capture the result of that try.
No panic, this does not really show or hide the keyboard. We just ask for the state.

To stay up-to-date, you can simply repeat the operation, eg every 200 milliseconds, using a Handler.

You find an implementation here: https://stackoverflow.com/a/27567074/2525452

i think this method will help you to find out is keybord is visible or not.

  public Boolean isSoftKeyBoardVisible(){ InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); if (imm.isAcceptingText()) { Log.d(TAG,"Software Keyboard was shown"); return true; } else { Log.d(TAG,"Software Keyboard was not shown"); return false; } } 

Reuben Scratton's new answer (calculate the HeightDiff int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight(); ) will not work in activity if you set the translucent status bar mode.

if you use translucent status bar , activityRootView.getHeight() will never change weather the soft keyboard is visible. it will always return the height of activity and status bar.

For example, Nexus 4, Android 5.0.1, set android:windowTranslucentStatus to true, it will return 1184 forever, even the ime have opend. If you set android:windowTranslucentStatus to false, it will return Height correctly, if ime invisible,it return 1134(not include the status bar)。close the ime, it will return 5xx maybe (depends on ime's height)

I don't know weather this is a bug, I've try on 4.4.4 and 5.0.1, the result is same.

So, up to now, the second most agreed answer, Kachi's solution will be the most safe way to calcute the height of ime. Here's a copy:

 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.bottom - r.top); if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard... ... do something here } } }); 

A method that doesn't need a LayoutListener

In my case, I would like to save the state of the keyboard before replacing my Fragment. I call the method hideSoftInputFromWindow from onSaveInstanceState , which closes the keyboard and returns me whether the keyboard was visible or not.

This method is straightforward but may change the state of your keyboard.

I know that this is a old post but I think this is the simplest approach that I know and my test device is Nexus 5. I haven't tried it in other devices. Hope that others will share their approach if they find my code is not good 🙂

 public static boolean isKeyboardShown(Context context, View view) { if (context == null || view == null) { return false; } InputMethodManager imm = (InputMethodManager) context .getSystemService(Context.INPUT_METHOD_SERVICE); return imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } 

imm.hideSoftInputFromWindow returns boolean.

Thanks,

 if (keyopen()) { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY,0); } 

The above function is what I use to check if a Keyboard is visible. If it is, then I close it.

Below shows the two methods requinetworking.

First, define the workable Window height in onCreate.

 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // add to onCreate method Rect rectgle= new Rect(); Window window= getWindow(); window.getDecorView().getWindowVisibleDisplayFrame(rectgle); sheight= rectgle.bottom; // } 

Then, add a boolean method that gets the Window height at that instance. If it does not match the original (assuming you are not changing it along the way…) then, the keyboard is open.

 public boolean keyopen() { Rect rectgle= new Rect(); Window window= getWindow(); window.getDecorView().getWindowVisibleDisplayFrame(rectgle); int curheight= rectgle.bottom; if (curheight!=sheight) { return true; } else { return false; } } 

Frotz!

I know how exact you can determine if keyboard is hidden or not.

 public int getStatusBarHeight() { int result = 0; int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { result = getResources().getDimensionPixelSize(resourceId); } return result; } public int getNavigationBarHeight() { int result = 0; int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android"); if (resourceId > 0) { result = getResources().getDimensionPixelSize(resourceId); } return result; } public boolean isKeyboardHidden() { int delta = mRootView.getRootView().getHeight() - mRootView.getHeight() - getNavigationBarHeight() - getStatusBarHeight() - getSupportActionBar().getHeight(); return delta <= 0; } 

This works for tablets. When navigationbar is shown horizontally.

Think has a easy way, like this:

 InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.isActive(); 

You can also see if him is active in a specific view:

 imm.isActive(View v);