studio getkeycode event edittext app_switch android android-support-library onkeydown onkeyup

android - getkeycode - Se actualizó a AppCompat v22.1.0 y ahora onKeyDown y onKeyUp no se activan cuando se presiona la tecla de menú



keyevent android studio (2)

En lugar de onKeyUp() o onKeyDown() , uno simplemente puede usar dispatchKeyEvent() . Mira el siguiente código de android-developers.blogspot.com .

@Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { // Tell the framework to start tracking this event. getKeyDispatcherState().startTracking(event, this); return true; } else if (event.getAction() == KeyEvent.ACTION_UP) { getKeyDispatcherState().handleUpEvent(event); if (event.isTracking() && !event.isCanceled()) { // DO BACK ACTION HERE return true; } } return super.dispatchKeyEvent(event); } else { return super.dispatchKeyEvent(event); } }

Acabo de actualizar mi aplicación para usar el recientemente lanzado AppCompat v22.1.0 y ahora onKeyDown y onKeyUp no se activan cuando se presiona la tecla de menú. Las otras teclas activan correctamente onKeyDown y onKeyUp , pero cuando onKeyUp la tecla de menú no ocurre nada. Si bajé a v22.0.0 todo vuelve a funcionar correctamente.

¿Cómo lo arreglo?


Actualización 23 de agosto

Esto se ha corregido de nuevo en la v23.0.0 de la biblioteca de soporte de appcompat-v7. Actualiza a la última versión para ver esto arreglado.

Actualización 19 de julio

Desafortunadamente, AppCompat v22.2.1 rompió los eventos onKeyDown y onKeyUp again . Acabo de actualizar AppCompatActivityMenuKeyInterceptor para admitir v22.1.x y también v22.2.1

Actualización 29 de mayo

Esto stated en la v22.2.0 de la biblioteca de soporte de appcompat-v7. Actualiza a la última versión para ver esto arreglado.

Desafortunadamente, AppCompat v22.1.0 intercepta los eventos onKeyDown y onKeyUp y no los propaga cuando se presiona la tecla de menú. La única solución posible consiste en utilizar Reflection para interceptar los eventos onKeyDown y onKeyUp antes de que lo haga AppCompat.

Agrega esta clase a tu proyecto:

public class AppCompatActivityMenuKeyInterceptor { private static final String FIELD_NAME_DELEGATE = "mDelegate"; private static final String FIELD_NAME_WINDOW = "mWindow"; public static void intercept(AppCompatActivity appCompatActivity) { new AppCompatActivityMenuKeyInterceptor(appCompatActivity); } private AppCompatActivityMenuKeyInterceptor(AppCompatActivity activity) { try { Field mDelegateField = AppCompatActivity.class.getDeclaredField(FIELD_NAME_DELEGATE); mDelegateField.setAccessible(true); Object mDelegate = mDelegateField.get(activity); Class mDelegateClass = mDelegate.getClass().getSuperclass(); Field mWindowField = null; while (mDelegateClass != null) { try { mWindowField = mDelegateClass.getDeclaredField(FIELD_NAME_WINDOW); break; } catch (NoSuchFieldException ignored) { } mDelegateClass = mDelegateClass.getSuperclass(); } if (mWindowField == null) throw new NoSuchFieldException(FIELD_NAME_WINDOW); mWindowField.setAccessible(true); Window mWindow = (Window) mWindowField.get(mDelegate); Window.Callback mOriginalWindowCallback = mWindow.getCallback(); mWindow.setCallback(new AppCompatWindowCallbackCustom(mOriginalWindowCallback, activity)); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } private class AppCompatWindowCallbackCustom extends WindowCallbackWrapper { private WeakReference<AppCompatActivity> mActivityWeak; public AppCompatWindowCallbackCustom(Window.Callback wrapped, AppCompatActivity appCompatActivity) { super(wrapped); mActivityWeak = new WeakReference<AppCompatActivity>(appCompatActivity); } @Override public boolean dispatchKeyEvent(KeyEvent event) { final int keyCode = event.getKeyCode(); AppCompatActivity appCompatActivity = mActivityWeak.get(); if (appCompatActivity != null && keyCode == KeyEvent.KEYCODE_MENU) { if (appCompatActivity.dispatchKeyEvent(event)) return true; } return super.dispatchKeyEvent(event); } } }

Llame a AppCompatActivityMenuKeyInterceptor.intercept(this) en el onCreate de su actividad:

public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //Initialize the interceptor AppCompatActivityMenuKeyInterceptor.intercept(this); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // Now onKeyDown is called also for KEYCODE_MENU if (keyCode == KeyEvent.KEYCODE_MENU) { //do your stuff //return false if you want to propagate the //KeyEvent to AppCompat, return true otherwise return false; } return super.onKeyDown(keyCode, event); } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { // Now onKeyUp is called also for KEYCODE_MENU if (keyCode == KeyEvent.KEYCODE_MENU) { //do your stuff //return false if you want to propagate the //KeyEvent to AppCompat, return true otherwise return false; } return super.onKeyUp(keyCode, event); } }

Si usa ProGuard o DexGuard, agregue estas reglas a su configuración:

-keepclassmembers class android.support.v7.app.AppCompatActivity { private android.support.v7.app.AppCompatDelegate mDelegate; } -keepclassmembers class android.support.v7.app.AppCompatDelegateImplBase { final android.view.Window mWindow; }

Ahora su actividad puede recibir eventos onKeyDown y onKeyUp también para la tecla de menú.