Android: Detectar el botón ACTION_UP fuera del evento

Estoy teniendo un problema con un botón personalizado que construí. Consiste en una caja y una pequeña línea debajo de ella.

El botón se anima hacia abajo verticalmente cuando se pulsa sobre él y hacia arriba de nuevo cuando se suelta. Esto se maneja en el CustomButton.class:

super.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { buttonContent.startAnimation(rectMoveDown); colorDown.start(); return false; } if (event.getActionMasked() == MotionEvent.ACTION_UP) { buttonContent.startAnimation(rectMoveUp); colorUp.start(); return false; } return false; } }); 

Luego, en el resto de la aplicación, utilizo este botón y le asigno un clicklistener. Por lo tanto devuelvo falso (creo que es correcto al menos) ya que no quiero consumir el evento, sino pasarlo a la lista de clics en la jerarquía.

Sin embargo, el problema surge cuando presiono por primera vez el botón, mueva el dedo fuera del botón y suelte la pantalla. A continuación, el botón no muestra la animación realizada en el listener ACTION_UP.

¿Alguien tiene una pista de cómo arreglar esto?

¡Encontré cómo podría solucionarlo después de más pruebas!

Después de leer un poco más en la documentación encontré que MotionEvent.ACTION_CANCEL hace exactamente lo que necesito:

El gesto actual ha sido abortado. No recibirás más puntos en él. Debe tratar esto como un evento ascendente, pero no realizar ninguna acción que normalmente haría.

Así que ahora mi TouchListener se parece a esto (y funciona como debería):

 super.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: buttonContent.startAnimation(rectMoveDown); colorDown.start(); return false; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: buttonContent.startAnimation(rectMoveUp); colorUp.start(); return false; } return false; } }); 

No fue que empecé a usar el switch-case que lo solucionó, pero lo cambié para que el código se vea mejor. Como puede ver, manejo el ACTION_UP y el ACTION_CANCEL de la misma manera.

Devuelvo false en todas partes para que OnClickListener desencadene lo que no sería si devuelve true.

Debería usar switch en lugar de if y devolver true en los casos:

 public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_UP: // Some code return true; case MotionEvent.ACTION_DOWN: // Some code return true; } return false; } 

Esto funcionó para mí, espero que esto le ayuda

  • Reducir animadamente el tamaño del botón en la prensa y recuperar su tamaño en la versión
  • Usando OnTouchListener y OnLongClickListener interfiere entre sí
  • Disparar Evento táctil desde la vista DialogFragment a la vista de actividad principal
  • Incorporación de ListView dentro de la Galería
  • ¿Cómo puedo mantener los eventos de ontouch manejados por un widget incluso si las coordenadas de tacto ya no están dentro del widget, en android
  • ¿Cómo puedo pasar Touch Listeners a la vista personalizada para arrastrar y soltar?
  • Android deja de enviar eventos onTouch
  • ¿Cómo manejar eventos de toque en un fragmento?
  • Android: ¿Qué uso tiene AnchorView de MediaController?
  • Hacer diferencias entre setOnClickListener y setOnTouchListener
  • Pase Android NestedScrollView desplazamientos horizontales a un padre Ver
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.