OnTouchEvent () no se activará si se invoca setSystemUiVisibility (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)

Yo lo llamo

getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) 

Cuando mi aplicación empieza a hacer que mi aplicación pueda mostrar la pantalla completa.

Quiero que la interfaz de usuario de mi aplicación aparezca cuando se toca la pantalla, pero Activity.onTouchEvent() no se activa hasta que se toca la pantalla una segunda vez. Al tocar por primera vez, sólo se muestran las teclas virtuales.

Por lo tanto, tengo que activar la interfaz de usuario de mi aplicación para que aparezca

 public void onSystemUiVisibilityChange(int visibility) { if (visibility == View.SYSTEM_UI_FLAG_VISIBLE) { // show my APP UI } } 

Pero onSystemUiVisibilityChange with View.SYSTEM_UI_FLAG_VISIBLE será invocado NO una vez por toque (3 veces en mi Galaxy Nexus) por sistema, especialmente si el usuario toca la pantalla muy rápido / a menudo.

Proyecto lib 4.0 o 4.03. Galaxia Samsung (9250) con 4.03.

Android 4.4 (API Level 19) introduce un nuevo indicador SYSTEM_UI_FLAG_IMMERSIVE para setSystemUiVisibility() que permite que tu aplicación setSystemUiVisibility() verdaderamente "pantalla completa". Este indicador, cuando se combina con los SYSTEM_UI_FLAG_HIDE_NAVIGATION y SYSTEM_UI_FLAG_FULLSCREEN , oculta las barras de navegación y estado y permite que su aplicación capture todos los eventos de toque en la pantalla.

Esto funcionó para mí:

  setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() { @Override public void onSystemUiVisibilityChange(int visibility) { if ((visibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) { // show my app UI } } }); 

Lo que he hecho es importado por primera vez android.view.GestureDetector para poder usarlo para detectar gestos. Android tiene varios gestos predeterminados que se detectan automáticamente en la clase GestureDector . La mayor parte de esta información se encuentra aquí , pero a continuación está el código en una forma que he utilizado en un proyecto real que funciona.

Primero he hecho una clase anónima en mi Actividad (esto puede anidarse donde sea, pero tienden a hacer mis clases anónimas en la parte inferior, justo antes del corchete de cierre). NOTA: También puede implementar OnGestureListener como parte de su clase, también.

El código de abajo es para usar la detección de gestos para dar un simple ocultar / mostrar.

He declarado y definido mi barra de acción (mi interfaz de usuario, que está inicialmente oculta) como una variable de instancia, por lo que puedo acceder a ella aquí y en cualquier otro lugar, pero se puede sustituir por un getActionBar().show() y getActionBar().hide() en el caso de que no quiera declararlo como una variable de instancia. Sustituya su interfaz de usuario en el lugar de la actionBar de actionBar aquí:

 public class Example extends ActionBarActivity { // declared in onCreate() method private android.support.v7.app.ActionBar actionBar; private GestureDetectorCompat mDetector; private YourView view1; private YourView view2; private YourView view3; private YourView view4; // some other code class GestureListener extends GestureDetector.SimpleOnGestureListener { private static final String DEBUG_TAG = "Gestures in Example Class"; @Override public boolean onDoubleTap(MotionEvent event) { Log.d(DEBUG_TAG, "onDoubleTap: " + event.toString()); // if there is a double tap, show the action bar actionBar.show(); return true; } @Override public boolean onSingleTapConfirmed(MotionEvent event) { Log.d(DEBUG_TAG, "onSingleTapConfirmed: " + event.toString()); // if the tap is below the action bar, hide the action bar if (event.getRawY() > getResources().getDimension(R.dimen.abc_action_bar_default_height)) { actionBar.hide(); return true; } return false; } @Override public boolean onDown(MotionEvent event) { return true; } } // end-of-Example Class 

Entonces en mi onCreate() he declarado mi GestureDetector y también (opcionalmente) mis GestureListeners :

 private GestureDetectorCompat mDetector; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // some code here mDetector = new GestureDetectorCompat(this, new GestureListener()); // this code is for more advanced view logic not needed for a basic set-up //setGestureListeners(); } // end-of-method onCreate() 

Entonces para enviar realmente gestos a ser procesados ​​proveemos las instrucciones para hacer eso, hay dos maneras sé sobre, primero el más simple:

 /** * This method recognizes a touchEvent and passes it to your custom GestureListener * class. */ @Override public boolean onTouchEvent(MotionEvent event){ this.mDetector.onTouchEvent(event); return super.onTouchEvent(event); } 

La segunda forma es más compleja, pero si sólo desea reconocer eventos táctiles en determinadas View en su diseño, como en el caso en que tiene vistas superpuestas y sólo puede acceder a la View superior, puede crear una clase personalizada para pasar el evento Alrededor o arriba:

 class MyOnTouchListener implements View.OnTouchListener { public boolean onTouch(View v, MotionEvent event) { if (v.equals(view4)) { return mDetector.onTouchEvent(event); } else return false; } } // end-of-class MyOnTouchListener 

Y luego usarlo aquí:

 public void setGestureListeners() { /* when we return false for any of these onTouch methods * it means that the the touchEvent is passed onto the next View. * The order in which touchEvents are sent to are in the order they * are declared. */ view1.setOnTouchListener(new MyOnTouchListener()); view2.setOnTouchListener(new MyOnTouchListener()); view3.setOnTouchListener(new MyOnTouchListener()); view4.setOnTouchListener(new MyOnTouchListener()); } // end-of-method setGestureListeners() 

En mi método setGestureListeners , les di todo el mismo conjunto de comandos, que esencialmente sólo reconoce touchEvents en view4 . De lo contrario, sólo pasa el touchEvent a la siguiente vista.

Este es el código que utiliza AppCompat , pero si no está construyendo versiones anteriores, puede utilizar el GestureDetector y ActionBar .

¿Ha intentado agregar código para mostrar sólo su interfaz de usuario cuando el estado ha cambiado? Tienes que mantener la última visibilidad conocida y solo mostrar tu interfaz de usuario al ser visible por primera vez:

 int mLastSystemUiVis; @Override public void onSystemUiVisibilityChange(int visibility) { int diff = mLastSystemUiVis ^ visibility; mLastSystemUiVis = visibility; if ((diff&SYSTEM_UI_FLAG_VISIBLE) != 0 && (visibility&SYSTEM_UI_FLAG_VISIBLE) == 0) { // DISPLAY YOUR UI } } 

Ejemplo de código adoptado de los documentos Android

Tengo este problema también, y he encontrado este http://developer.android.com/reference/android/view/View.html#SYSTEM_UI_FLAG_HIDE_NAVIGATION

Así que, no hay manera de ayudar. Incluso la aplicación de sistema de Android comprimida en la galería utiliza SYSTEM_UI_FLAG_LOW_PROFILE en lugar de SYSTEM_UI_FLAG_HIDE_NAVIGATION en la vista de página de fotos. Esto es al menos lo que podemos hacer.

Tuve un problema muy similar con intentar actualizar la interfaz de usuario de un onTouchEvent() requiere dos toques para trabajar, e intenté un montón de cosas elaboradas antes de finalmente conseguir que funcione en el primer clic.

En mi caso, estaba mostrando un elemento previamente oculto, luego obtener su altura, luego mover un botón hacia abajo por esa altura. El problema que encontré es que la altura se mostraba como 0 hasta después del primer evento de toque terminado. Pude resolver esto llamando show () durante ACTION_UP para el onTouchEvent() lugar de su ACTION_DOWN . ¿Tal vez funcionaría si hiciera algo similar?

Tratar de usar:

GetWindow (). GetDecorView (). SetSystemUiVisibility (View.GONE);

en lugar:

GetWindow (). GetDecorView (). SetSystemUiVisibility (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)

Después de que usted puede utilizar la actividad normal en pantalla completa y si desea que las teclas de navegación que usted necesita para deslizar de abajo hacia arriba. Trabajo para mí en Galaxy Tab 2 con Android 4.1.2

El método Activity.onTouchEvent() se llama al final de la cadena de respuesta (es decir, después de que todas las otras vistas han tenido la oportunidad de consumir el evento). Si pulsa en una vista que esté interesada en el tacto (es decir, un Button o EditText ) hay una buena probabilidad de que su actividad nunca verá ese evento.

Si desea tener acceso a los toques antes de que se envíen a su (s) vista (s), reemplace Activity.dispatchTouchEvent() , que es el método que se llama al principio de la cadena de sucesos:

 @Override public boolean dispatchTouchEvent(MotionEvent event) { //Check the event and do magic here, such as... if (event.getAction() == MotionEvent.ACTION_DOWN) { } //Be careful not to override the return unless necessary return super.dispatchTouchEvent(event); } 

Tenga cuidado de no anular el valor de retorno de este método a menos que desee voluntariamente robar toques del resto de las vistas, un return true; innecesario return true; En este punto se romperá el manejo de otro toque.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.