Detectar cuando el usuario ha descartado el teclado virtual

Tengo un widget EditText en mi vista. Cuando el usuario selecciona el widget EditText, muestro algunas instrucciones y aparece el teclado virtual.

Yo uso un OnEditorActionListener para detectar cuando el usuario ha completado la entrada de texto y despedir el teclado, ocultar las instrucciones y realizar alguna acción.

Mi problema es cuando el usuario rechaza el teclado presionando la tecla BACK. El sistema operativo desecha el teclado, pero mis instrucciones (que tengo que esconder) siguen visibles.

He intentado sobreescribir OnKeyDown, pero eso no parece ser llamado cuando se utiliza el botón BACK para descartar el teclado.

He intentado establecer un OnKeyListener en el widget EditText, pero que no parece ser llamado tampoco.

¿Cómo puedo detectar cuando se desactiva el teclado virtual?

Esta pregunta (sin respuesta aún y mirando sombrío) parece estar haciendo la misma pregunta: ¿Cómo comprobar la visibilidad del teclado de software en Android?

Conozco una manera de hacer esto. Subclase el EditText y el implemento:

@Override public boolean onKeyPreIme(int keyCode, KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { // Do your thing. return true; // So it is not propagated. } return super.dispatchKeyEvent(event); } 

Aquí hay un enlace sobre cómo usar tus vistas personalizadas (para cuando subclases EditText): http://developer.android.com/guide/topics/ui/custom-components.html

Jay, tu solución es buena! Gracias 🙂

 public class EditTextBackEvent extends EditText { private EditTextImeBackListener mOnImeBack; public EditTextBackEvent(Context context) { super(context); } public EditTextBackEvent(Context context, AttributeSet attrs) { super(context, attrs); } public EditTextBackEvent(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public boolean onKeyPreIme(int keyCode, KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { if (mOnImeBack != null) mOnImeBack.onImeBack(this, this.getText().toString()); } return super.dispatchKeyEvent(event); } public void setOnEditTextImeBackListener(EditTextImeBackListener listener) { mOnImeBack = listener; } } public interface EditTextImeBackListener { public abstract void onImeBack(EditTextBackEvent ctrl, String text); } 

Hice un ligero cambio en la solución de Jay llamando a super.onKeyPreIme ():

 _e = new EditText(inflater.getContext()) { @Override public boolean onKeyPreIme(int keyCode, KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK){ cancelTextInput(); } return super.onKeyPreIme(keyCode, event); } }; 

Maravillosa solución, Jay, +1!

Aquí está mi EditText personalizado para detectar si el teclado está mostrando o no

 /** * Created by TheFinestArtist on 9/24/15. */ public class KeyboardEditText extends EditText { public KeyboardEditText(Context context) { super(context); } public KeyboardEditText(Context context, AttributeSet attrs) { super(context, attrs); } public KeyboardEditText(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { super.onFocusChanged(focused, direction, previouslyFocusedRect); if (listener != null) listener.onStateChanged(this, true); } @Override public boolean onKeyPreIme(int keyCode, @NonNull KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { if (listener != null) listener.onStateChanged(this, false); } return super.onKeyPreIme(keyCode, event); } /** * Keyboard Listener */ KeyboardListener listener; public void setOnKeyboardListener(KeyboardListener listener) { this.listener = listener; } public interface KeyboardListener { void onStateChanged(KeyboardEditText keyboardEditText, boolean showing); } } 

Basta con crear una clase que se extienda Edittext y utilizar ese edittext en su código, sólo debe anular el siguiente método en el edittext personalizado:

 @Override public boolean onKeyPreIme(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { //Here it catch all back keys //Now you can do what you want. } else if (keyCode == KeyEvent.KEYCODE_MENU) { // Eat the event return true; } return false;} 

Aquí hay una solución con el oyente dominante. No tengo ni idea de por qué esto funciona, pero OnKeyListener funciona si usted acaba de sustituir puramente onKeyPreIme en su Custom EditText.

SomeClass.java

 customEditText.setOnKeyListener((v, keyCode, event) -> { if(event.getAction() == KeyEvent.ACTION_DOWN) { switch (keyCode) { case KeyEvent.KEYCODE_BACK: getPresenter().onBackPressed(); break; } } return false; }); 

CustomEditText.java

 @Override public boolean onKeyPreIme(int keyCode, KeyEvent event) { return super.dispatchKeyEvent(event); } 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.