No puede manejar simultáneamente los eventos de clic y de toque
Estoy tratando de manejar eventos táctiles y hacer clic en eventos en un botón. Hago lo siguiente:
button.setOnClickListener(clickListener); button.setOnTouchListener(touchListener);
Cuando cualquier oyente está registrado, las cosas funcionan bien, pero cuando intento usarlas solo se disparan los eventos de toque. ¿Alguna solución? ¿Qué estoy haciendo mal?
- Android Spinner - Cómo seleccionar la lista predeterminada a ninguna
- SetOnQueryTextFocusChangeListener vs setOnFocusChangeListener
- RecyclerView onclick se activa antes de que la animación del clic se complete
- Botón Onclick Listener en los diseños incluidos
- Preferencia de conmutador - Manejo de los dos onPreferenceChange y onPreferenceClick
Hay una diferencia sutil, pero muy importante entre el ClickListener
y el TouchListener
. El TouchListener
se ejecuta antes de que la vista pueda responder al evento. El ClickListener
recibirá su evento sólo después de que la vista lo haya manejado.
Así que cuando toca su pantalla, el TouchListener
se ejecuta primero y cuando devuelve true
para su evento, ClickListener
nunca lo obtendrá. Pero si presiona el trackball de su dispositivo, el ClickListener
debe ser disparado porque el TouchListener
no responderá a él.
Es un poco complicado.
Si estableces onTouchListener
debes devolver true
en ACTION_DOWN
, para decirle al sistema que he consumido el evento y que no llegará a otros oyentes.
Pero entonces OnClickListener
no se disparará.
Así que usted podría pensar, voy a hacer mi cosa allí y devolver false
para que yo pueda recibir clics también. Si lo hace, funcionará, pero no se suscribirá a otros eventos de toque próximos ( ACTION_MOVE
, ACTION_UP
). Por lo tanto, la única opción es devolver true
allí, pero luego no recibirá ningún evento de clic como dijimos previamente.
Por lo que necesita realizar el clic manualmente en el ACTION_UP
con view.performClick()
Esto funcionará.
Gracias a @urSus por una gran respuesta
Pero en ese caso cada toque realizará click, incluso ACTION_MOVE
Suponiendo que desea separar evento de move
y evento de click
, puede utilizar un pequeño truco
Defina un campo boolean
y utilícelo de la siguiente manera:
@Override public boolean onTouch(View view, MotionEvent motionEvent) { switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: shouldClick = true; . . break; case MotionEvent.ACTION_UP: if (shouldClick) view.performClick(); break; case MotionEvent.ACTION_POINTER_DOWN: break; case MotionEvent.ACTION_POINTER_UP: break; case MotionEvent.ACTION_MOVE: //Do your stuff shouldClick = false; break; } rootLayout.invalidate(); return true; }
¿Supongo que usted está volviendo true
en su OnTouchListener
? Esto consumirá el evento para que no se envíe para procesamiento adicional.
En una nota lateral – ¿cuál es el punto de tener tanto un oyente de clic y tacto?
Debería devolver un OnTouchListener
en su OnTouchListener
y también su OnClickListener
también será manejado.
button.setOnTouchListener(this);
Implementar la interfaz y el código aquí:
@Override public boolean onTouch(View view, MotionEvent motionEvent) { switch (view.getId()) { case R.id.send: switch(motionEvent.getAction()){ case MotionEvent.ACTION_DOWN: //when the user has pressed the button //do the needful here break; case MotionEvent.ACTION_UP: //when the user releases the button //do the needful here break; } break; } return false; }