¿Cómo manejar el toque fuera de la vista en Android?

He encontrado la implementación de "Undo Bar" utilizada en la aplicación de Gmail para Android. "UndoBar" es básicamente una vista que se muestra en la parte superior del diseño.

Desafortunadamente no es completa – no tiene funcionalidad de despedir la barra al tocar la pantalla fuera de la barra.

He implementado FrameLayout que anula onInterceptTouchEvent para manejar la barra de despedir, pero tocar la barra de acción no hace nada.

¿Hay alguna manera de manejar estos eventos desde la barra de acción?

Abajo hay una imagen con "UndoBar" mostrado. Lo que quiero lograr para manejar el tacto en la barra de acción representada por punto rojo.

Introduzca aquí la descripción de la imagen

Trate de reemplazar dispatchTouchEvent de su actividad.

 dispatchTouchEvent(MotionEvent event){ int x= event.getRawX(); int y= event.getRawY(); if(/*check bounds of your view*/){ // set your views visiblity to gone or what you want. } //for prevent consuming the event. return super().dispatchTouchEvent(event); } 

actualizar

 dispatchTouchEvent(MotionEvent event){ int x= event.getRawX(); int y= event.getRawY(); return super().dispatchTouchEvent(event)||[YourView].onTouch(event); } 

Para capturar eventos táctiles para toda la pantalla, incluyendo el ActionBar, agregue una vista a la ventana.

 View overlayView = new View(this); WindowManager.LayoutParams p = new WindowManager.LayoutParams(); p.gravity = Gravity.TOP; p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; p.token = overlayView.getWindowToken(); overlayView.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View view, MotionEvent event) { // Get the action bar int actionBarHeight = actionBar.getHeight(); if ((event.getAction() == MotionEvent.ACTION_DOWN) && (event.getRawY() < actionBarHeight)) { // Touch inside the actionBar so let's consume it // Do something return true; } return false; } }); WindowManager mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); mWindowManager.addView(overlayView, p); 

Espero que esto ayude.

¿Has probado un onTouchEvent en tu FrameLayout ..?

No lo he probado, pero creo que tiene sentido para mí que en caso de MotionEvent en esa acción ACTION_OUTSIDE disposición debe ser despedido.

Intente lo siguiente.

 public boolean onTouchEvent(MotionEvent event) { if(event.getAction() == MotionEvent.ACTION_OUTSIDE){ undoBar.setVisibility(View.GONE); } return true; } 

Hay 2 posibles soluciones.

Como mencioné en los comentarios, puedes implementar un listener de scroll en tu ListView y simple llamado hideUndoBar(true) en el scroll más leve.

O

Puede modificar el UndoBarController . Notará que la barra de deshacer es simplemente un View slap un OnFocusChange escucha en la View en el constructor y en el método show setFocus a la vista.

En su verificación OnFocusChange para ver si la vista ha perdido el foco y llame a hideUndoBar(true) .

Actualizar

He creado un Gist aquí https://gist.github.com/atgheb/5551961 que muestra cómo cambiar el UndoBarController para agregar la característica donde se oculta cuando pierde el foco.

No lo he probado pero no veo por qué no funcionará.

 params = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL|WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, PixelFormat.TRANSPARENT); 

Lo que realmente necesita es:

 WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL|WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH 

La documentación dice:

Indicador de ventana: si ha configurado FLAG_NOT_TOUCH_MODAL, puede configurar este indicador para que reciba un solo movimiento especial con la acción MotionEvent.ACTION_OUTSIDE para los toques que se producen fuera de su ventana.

Puede obtener todos los eventos táctiles en su Activity mediante el código siguiente. Supongo que este código obtendría los toques de ActionBar también.

 public class MainActivity extends Activity { ... // This example shows an Activity, but you would use the same approach if // you were subclassing a View. @Override public boolean onTouchEvent(MotionEvent event){ int action = MotionEventCompat.getActionMasked(event); switch(action) { case (MotionEvent.ACTION_DOWN) : Log.d(DEBUG_TAG,"Action was DOWN"); return true; case (MotionEvent.ACTION_MOVE) : Log.d(DEBUG_TAG,"Action was MOVE"); return true; case (MotionEvent.ACTION_UP) : Log.d(DEBUG_TAG,"Action was UP"); return true; case (MotionEvent.ACTION_CANCEL) : Log.d(DEBUG_TAG,"Action was CANCEL"); return true; case (MotionEvent.ACTION_OUTSIDE) : Log.d(DEBUG_TAG,"Movement occurred outside bounds " + "of current screen element"); return true; default : return super.onTouchEvent(event); } } 
  • ¿Cómo pasar el hipervínculo a Gmail en Intent ACTION_SEND?
  • Android: cómo abrir una vista de compositor de correo?
  • La línea Html (regla horizontal) no es compatible con el cliente de Gmail de Android
  • Buscando un ejemplo de trabajo (proyecto completo) para OAuth 2.0 Acceso a gmail
  • Android Oauth Exception con el transporte SMTP se conectan, con Android versión 2.3
  • Comprimir mapa de bits de la cámara
  • Cómo compartir archivos de almacenamiento interno con Gmail Client
  • Tire para actualizar como nueva aplicación gmail (4.5)
  • Android gmail apertura adjunto de aplicación URI problema con la nueva versión de la aplicación Gmail
  • Aplicación de Gmail de Android: adjunto de correo: problema de URI
  • Utilizar la autenticación de inicio de sesión de cuenta de Google para aplicaciones en Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.