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?

    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; } 
    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.