temas teclado sirve que para los google gboard funciona emojis configurar como cambiar activar android

android - sirve - Interceptar el botón Atrás desde el teclado suave



teclado google emoji (8)

Tengo la actividad con varios campos de entrada. Cuando comenzó la actividad, se muestra el teclado suave. Cuando el botón Atrás se presiona el teclado suave se cierra y para cerrar la actividad, necesito presionar el botón Atrás una vez más.

Entonces la pregunta: ¿es posible interceptar el botón Atrás para cerrar el teclado InputMethodService y finalizar la actividad con solo presionar el botón Atrás sin crear InputMethodService personalizado?

PD: Sé cómo interceptar el botón Atrás en otros casos: onKeyDown() o onBackPressed() pero en este caso no funciona: solo se intercepta la segunda pulsación del botón Atrás.



Me enteré de que anular el método dispatchKeyEventPreIme de la clase de diseño también funciona bien. Simplemente configure su actividad principal como un atributo e inicie 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); } }



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 hacer esto 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 función setActivity(...) .

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; } }); // Let the layout know we are going to be overriding the back button SearchLayout.setSearchActivity(this); }

Obviamente, la función initInputField() 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() { // It''s expensive, if running turn it off. DataHelper.cancelSearch(); hideKeyboard(); super.onBackPressed(); }

Entonces, cuando se llama a onBackPressed() 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; /** * The root element in the search bar layout. This is a custom view just to * override the handling of the back button. * */ 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; } /** * Overrides the handling of the back key to move back to the * previous sources or dismiss the search dialog, instead of * dismissing the input method. */ @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 tomar todo el crédito. Si comprueba la fuente de Android para el cuadro de diálogo Búsqueda rápida verá la procedencia de la idea.


Tuve éxito anulando 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.


Tuve el mismo problema, pero lo esquivé interceptando la tecla de retroceso. En mi caso (HTC Desire, Android 2.2, Application API Level 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(); }


Utilice el onKeyPreIme(int keyCode, KeyEvent event) y KeyEvent.KEYCODE_BACK evento KeyEvent.KEYCODE_BACK . Es muy simple sin hacer ningún código de fantasía.


onKeyDown () y onBackPressed () no funciona en este caso. Tienes que usar onKeyPreIme .

Inicialmente, debe crear texto de edición personalizado que extienda EditText. Y luego debe implementar el método onKeyPreIme que controla KeyEvent.KEYCODE_BACK . Después de esto, una presión hacia atrás lo suficiente para resolver su problema. Esta solución funciona para mí 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); } }