android - personalizar - teclado google
Detectando cuando el usuario ha descartado el teclado suave (8)
Tengo un widget EditText en mi opinión. Cuando el usuario selecciona el widget EditText, se muestran algunas instrucciones y aparece 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.
Intenté reemplazar OnKeyDown, pero parece que no se llama cuando el botón ATRÁS se usa para cerrar el teclado.
Intenté 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?
Aquí está mi EditText personalizado para detectar si el teclado se muestra 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);
}
}
Aquí hay una solución con el oyente clave. No tengo idea de por qué funciona esto, 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);
}
Conozco una manera de hacer esto. Subclase 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 usar tus vistas personalizadas (para cuando subclases EditText): http://developer.android.com/guide/topics/ui/custom-components.html
Esta pregunta (sin respuesta todavía y con aspecto sombrío) parece estar haciendo la misma pregunta: ¿Cómo verificar la visibilidad del teclado de software en Android?
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);
}
};
¡Solución maravillosa, Jay, +1!
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);
}
Simplemente cree una clase que extienda el texto de edición y use ese texto de edición en su código, simplemente debe anular el siguiente método en el texto de edición 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;}
Usando la respuesta de @ olivier_sdg, pero convertida a 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)
}