Sí, es completamente posible mostrar y ocultar el teclado e interceptar las llamadas al botón Atrás. Es un pequeño esfuerzo adicional, ya que se ha mencionado que no hay una forma directa de hacerlo en la API. La clave es anular boolean dispatchKeyEventPreIme(KeyEvent)
dentro de un diseño. Lo que hacemos es crear nuestro diseño. Elegí RelativeLayout ya que era la base de mi actividad.
<?xml version="1.0" encoding="utf-8"?>
<com.michaelhradek.superapp.utilities.SearchLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.michaelhradek.superapp"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/white">
Dentro de nuestra Actividad configuramos nuestros campos de entrada y llamamos a la setActivity(...)
función.
private void initInputField() {
mInputField = (EditText) findViewById(R.id.searchInput);
InputMethodManager imm =
(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED,
InputMethodManager.HIDE_IMPLICIT_ONLY);
mInputField.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
performSearch();
return true;
}
return false;
}
});
SearchLayout.setSearchActivity(this);
}
Obviamente, la initInputField()
función configura el campo de entrada. También habilita la tecla enter para ejecutar la funcionalidad (en mi caso una búsqueda).
@Override
public void onBackPressed() {
DataHelper.cancelSearch();
hideKeyboard();
super.onBackPressed();
}
Entonces, cuando onBackPressed()
se llama dentro de nuestro diseño, podemos hacer lo que queramos, como ocultar el teclado:
private void hideKeyboard() {
InputMethodManager imm = (InputMethodManager)
getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mInputField.getWindowToken(), 0);
}
De todos modos, aquí está mi anulación del RelativeLayout.
package com.michaelhradek.superapp.utilities;
import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.RelativeLayout;
public class SearchLayout extends RelativeLayout {
private static final String TAG = "SearchLayout";
private static Activity mSearchActivity;;
public SearchLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SearchLayout(Context context) {
super(context);
}
public static void setSearchActivity(Activity searchActivity) {
mSearchActivity = searchActivity;
}
@Override
public boolean dispatchKeyEventPreIme(KeyEvent event) {
Log.d(TAG, "dispatchKeyEventPreIme(" + event + ")");
if (mSearchActivity != null &&
event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
KeyEvent.DispatcherState state = getKeyDispatcherState();
if (state != null) {
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getRepeatCount() == 0) {
state.startTracking(event, this);
return true;
} else if (event.getAction() == KeyEvent.ACTION_UP
&& !event.isCanceled() && state.isTracking(event)) {
mSearchActivity.onBackPressed();
return true;
}
}
}
return super.dispatchKeyEventPreIme(event);
}
}
Desafortunadamente, no puedo llevarme todo el crédito. Si comprueba la fuente de Android para el cuadro de diálogo de búsqueda rápido , verá de dónde vino la idea.
getContext()
aActivity
. Siempre que el contexto del diseño sea la actividad en cuestión, por supuesto. Pero no sé si no podría ser.onKeyDown () y onBackPressed () no funcionan para este caso. Tienes que usar onKeyPreIme .
Inicialmente, debe crear un texto de edición personalizado que amplíe EditText. Y luego debe implementar el método onKeyPreIme que controla KeyEvent.KEYCODE_BACK . Después de esto, presione una vez hacia atrás lo suficiente para resolver su problema. Esta solución me funciona perfectamente.
CustomEditText.java
public class CustomEditText extends EditText { public CustomEditText(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onKeyPreIme(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { // User has pressed Back key. So hide the keyboard InputMethodManager mgr = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); mgr.hideSoftInputFromWindow(this.getWindowToken(), 0); // TODO: Hide your view as you do it in your activity } return false; }
En tu XML
<com.YOURAPP.CustomEditText android:id="@+id/CEditText" android:layout_height="wrap_content" android:layout_width="match_parent"/>
En tu actividad
public class MainActivity extends Activity { private CustomEditText editText; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText = (CustomEditText) findViewById(R.id.CEditText); } }
fuente
Descubrí que anular el método dispatchKeyEventPreIme de Layout Class también funciona bien. Simplemente configure su Actividad principal como un atributo y ejecute un método predefinido.
public class LinearLayoutGradient extends LinearLayout { MainActivity a; public void setMainActivity(MainActivity a) { this.a = a; } @Override public boolean dispatchKeyEventPreIme(KeyEvent event) { if (a != null) { InputMethodManager imm = (InputMethodManager) a .getSystemService(Context.INPUT_METHOD_SERVICE); if (imm.isActive() && event.getKeyCode() == KeyEvent.KEYCODE_BACK) { a.launchMethod; } } return super.dispatchKeyEventPreIme(event); } }
fuente
<?xml version="1.0" encoding="utf-8"?> <view class="package.LinearLayoutGradient"...
Tuve éxito al anular dispatchKeyEvent :
@Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { finish(); return true; } return super.dispatchKeyEvent(event); }
Oculta el teclado y finaliza la actividad.
fuente
¿Cómo está mostrando el teclado virtual?
Si está utilizando
InputMethodManager.showSoftInput()
, puede intentar pasar aResultReceiver
e implementaronReceiveResult()
para manejarRESULT_HIDDEN
http://developer.android.com/reference/android/view/inputmethod/InputMethodManager.html
fuente
showSoftInput()
no muestra el teclado en mi teléfono ni en mi emulador, así que lo usotoggleSoftInput()
Tuve el mismo problema, pero lo solucioné interceptando la pulsación de la tecla Atrás. En mi caso (HTC Desire, Android 2.2, API de aplicación Nivel 4) cierra el Teclado e inmediatamente finaliza la Actividad. No sé por qué esto no debería funcionar para usted también:
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { return true; } return super.onKeyDown(keyCode, event); } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { onBackPressed(); return true; } return super.onKeyUp(keyCode, event); } /** * Called when the activity has detected the user's press of the back key */ private void onBackPressed() { Log.e(TAG, "back pressed"); finish(); }
fuente
Utilice el
onKeyPreIme(int keyCode, KeyEvent event)
método y verifique elKeyEvent.KEYCODE_BACK
evento. Es muy simple sin necesidad de realizar ninguna codificación elegante.fuente
Pruebe este código en su implementación BackPressed ( Block Back Button en Android ):
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(myEditText.getWindowToken(), 0);
Te sugiero que eches un vistazo @ Cerrar / ocultar el teclado virtual de Android
fuente
onBackPressed()
que no funciona. Y solo después de que el segundo programa de prensa caiga en elonBackPressed()
.mi versión de la solución @mhradek:
Diseño
class BazingaLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : ConstraintLayout(context, attrs, defStyleAttr) { var activity: Activity? = null override fun dispatchKeyEventPreIme(event: KeyEvent): Boolean { activity?.let { if (event.keyCode == KeyEvent.KEYCODE_BACK) { val state = keyDispatcherState if (state != null) { if (event.action == KeyEvent.ACTION_DOWN && event.repeatCount == 0) { state.startTracking(event, this) return true } else if (event.action == KeyEvent.ACTION_UP && !event.isCanceled && state.isTracking(event)) { it.onBackPressed() return true } } } } return super.dispatchKeyEventPreIme(event) }
}
archivo xml
<com... BazingaLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/grey"> </com... BazingaLayout>
Fragmento
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { (view as BazingaLayout).activity = activity super.onViewCreated(view, savedInstanceState) }
fuente