2010-08-06 23 views
89

Tengo un widget EditText en mi vista. Cuando el usuario selecciona el widget EditText, se muestran algunas instrucciones y aparece el teclado virtual.Detectando cuando el usuario ha descartado el teclado virtual

Uso un OnEditorActionListener para detectar cuando el usuario ha completado la entrada de texto y descarto el teclado, oculto las instrucciones y realizo alguna acción.

Mi problema es cuando el usuario cierra el teclado presionando la tecla ATRÁS. El sistema operativo cierra el teclado, pero mis instrucciones (que necesito ocultar) siguen visibles.

He intentado reemplazar OnKeyDown, pero parece que no se llama cuando el botón ATRÁS se usa para cerrar el teclado.

He intentado configurar un OnKeyListener en el widget EditText, pero parece que tampoco se llama.

¿Cómo puedo detectar cuándo se está descartando el teclado virtual?

Respuesta

144

sé una manera de hacer esto. Subclase el EditarTexto e implementar:

@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 utilizar sus puntos de vista personalizados (para cuando subclase EditarTexto): http://developer.android.com/guide/topics/ui/custom-components.html

+1

estoy recibiendo informes de Android usuarios con teclados de hardware que haciendo esto de alguna manera interfiere con las pulsaciones de teclas. No tengo ninguna información adicional en este momento. – esilver

+0

He estado buscando en varias soluciones, este es de lejos el mejor! – Friesgaard

+9

Espera, espera, solo lo miré por tercera vez. ¿No debería ser la super llamada a 'onKeyPreIme'? ¿O hay una razón particular para que no sea así? – Erhannis

110

Jay, su 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); 
} 
+0

@oliver_sdg lo siento por la pregunta de novato, pero ¿cómo creo el controlador de eventos para EditText? – Manolis

+1

+1 Gracias por esa respuesta tan útil e inteligente. Salvaste a mi hombre de hoy Muchas gracias otra vez;) – Sajmon

+0

¿Alguna razón en particular por la que queremos detectar 'KeyEvent.ACTION_UP' también? –

17

me hizo un ligero cambio en la solución de Jay llamando 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); 
    } 
}; 

solución maravillosa, Jay, 1!

4

Basta con crear una clase que se extiende EDITTEXT y el uso que EditarTexto en su código, que sólo debe reemplazar el método siguiente en el EditarTexto 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;} 
+0

¿Hay una forma de detectar cuándo se abre el teclado? – powder366

13

Aquí es mi costumbre EditarTexto 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); 
    } 
} 
1

Aquí hay una solución con el oyente de claves. No tengo idea de por qué funciona, pero OnKeyListener funciona si solo sobreescribes onKeyPreIme en tu EditText personalizado.

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

Utilizar el servicio de @ olivier_sdg, pero convertidos en Kotlin:

class KeyboardEditText : EditText { 

    private var mOnImeBack: EditTextImeBackListener? = null 

    constructor(context: Context) : super(context) 
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) 
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) 

    override fun onKeyPreIme(keyCode: Int, event: KeyEvent): Boolean { 
     if (event.keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) { 
      if (mOnImeBack != null) 
       mOnImeBack!!.onImeBack(this, this.text.toString()) 
     } 
     return super.dispatchKeyEvent(event) 
    } 

    fun setOnEditTextImeBackListener(listener: EditTextImeBackListener) { 
     mOnImeBack = listener 
    } 

} 

interface EditTextImeBackListener { 
    fun onImeBack(ctrl: KeyboardEditText, text: String) 
} 
Cuestiones relacionadas