Estoy tratando de manejar eventos de toque y eventos de clic en un botón. Hago lo siguiente:

button.setOnClickListener(clickListener);
button.setOnTouchListener(touchListener);

Cuando uno escucha que está inscrita cosas funcionan bien pero cuando trato de usar ambos sólo los eventos de toque son despedidos. Cualquier solución? ¿Qué estoy haciendo mal?

10 Comentarios

  1. 39

    Hay una sutil pero importante diferencia entre el ClickListener y la TouchListener. El TouchListener es ejecutado antes de que la vista puede responder al evento. El ClickListener recibirá su evento sólo después de la vista se ha manejado.

    Así que cuando se toca la pantalla, el TouchListener se ejecuta primero y cuando regrese true para su evento, la ClickListener nunca van a llegar a ella. Pero si usted pulse el trackball de tu dispositivo, la ClickListener debe ser despedido porque la TouchListener no responder a ella.

  2. 67

    Es un poco complicado.

    Si establece onTouchListener usted necesita para volver true en ACTION_DOWN, para decirle al sistema que he consumido el evento y que no se propague a otros oyentes.

    Pero luego OnClickListener no ser despedido.

    Por lo que se podría pensar, solo voy a hacer lo mío allí y volver a false para que yo pueda recibir clics demasiado.
    Si lo hace, va a trabajar, pero no se suscribe a otras próximos eventos de toque (ACTION_MOVE, ACTION_UP)
    Por lo tanto, la única opción es volver true allí, pero entonces usted no recibirá ningún haga clic en eventos como hemos dicho anteriormente.

    Por lo que necesita para realizar el clic manualmente en el ACTION_UP con view.performClick()

    Este trabajo.

    • La parte clave de esto es «lo que necesita para realizar el clic manualmente en el ACTION_UP», gracias, señor
    • Esta es realmente la mejor respuesta. En mi ACTION_MOVE, empiezo interceptar eventos de toque si un determinado deltaX que se alcanza el umbral. Si me pongo a ACTION_UP y que deltaX umbral nunca fue cumplido, yo fuego listView.performClick(), de lo contrario, me desliza el dedo.
    • Esto, obviamente, debe ser la respuesta.
    • Gran respuesta. Keep it up
  3. 16

    Gracias a @urSus para la gran respuesta

    Pero en ese caso cada toque llevará a cabo clic, Incluso ACTION_MOVE

    Suponiendo que se quiere separar move evento y click evento puede utilizar un pequeño truco

    definir un boolean de campo y uso como esta:

     @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;
            }
    • Gran respuesta. Keep it up
    • realizar haga clic en el punto de vista del método ? o un método personalizado donde tenemos que realizar haga clic en
    • es cada vista y sus subclases método
    • Funciona, si return true; en MotionEvent.ACTION_DOWN rama, quitar MotionEvent.ACTION_MOVE rama, obtener el movimiento de diferencia en MotionEvent.ACTION_UP rama. Consulte stackoverflow.com/questions/17831395/…
    • realmente esta respuesta es mejor en todos pregunta similar
  4. 5

    Supongo que está regresando true en su OnTouchListener? Que consumirá el evento por lo que no será enviado para el procesamiento.

    En una nota de lado – ¿cuál es el punto de tener tanto un clic y toque oyente?

    • El cliente quiere un sonido que se reproduce cuando el botón se presiona y suelta, lo hago en el ‘ACTION_UP’ y ‘ACTION_DOWN’ eventos. Y el evento click no la lógica. Ahora voy a tener que manejar la lógica en el toque propio evento.
    • Un botón que puede ser arrastrado, a continuación, hace clic cuando haya terminado?
  5. 2

    Todas las anteriores respuesta se dijo que nosotros no puede manejar tanto setOnTouchListener y setOnClickListener.

    No obstante, creo que podemos manejar tanto por return false en setOnTouchListener

    Ejemplo

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    
        button = findViewById(R.id.button)
        button.setOnClickListener {
            Log.i("TAG", "onClick")
        }
    
        button.setOnTouchListener { v, event ->
            Log.i("TAG", "onTouch " + event.action)
            false
        }
    }

    Cuando hago clic en Button, logcat mostrará como

    I/TAG: onTouch 0
    I/TAG: onTouch 1
    I/TAG: onClick
  6. 0
    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;
    }
  7. 0

    Para que ambos eventos posibles en el gridview,sólo por hacer la devolución de toque de escucha»falsa» de la siguiente manera,esto funcionó para mí.

    **GridView myView = findViewById(R.id.grid_view);
    myView.setOnTouchListener(new OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            //... Respond to touch events
            return false;
        }
    });**

    de esta manera ambos eventos se puede lograr

  8. 0
    ## Exact working solution for both click action and touch listener(dragging) ##
    private int initialX;
    private int initialY;
    private float initialTouchX;
    private float initialTouchY;
    private float CLICK_ACTION_THRESHOLD = 0.5f;
    private float startX;
    private float startY;
    @Override
    public boolean onTouch(View view, MotionEvent event) {
    switch (view.getId()) {
    case R.id.chat_head_profile_iv:
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
    //remember the initial position.
    initialX = params.x;
    initialY = params.y;
    startX = event.getX();
    startY = event.getY();
    //get the touch location
    initialTouchX = event.getRawX();
    initialTouchY = event.getRawY();
    return true;
    case MotionEvent.ACTION_UP:
    float endX = event.getX();
    float endY = event.getY();
    if (shouldClickActionWork(startX, endX, startY, endY)) {
    openScreen();//WE HAVE A CLICK!!
    }
    return true;
    case MotionEvent.ACTION_MOVE:
    //Calculate the X and Y coordinates of the view.
    params.x = initialX + (int) (event.getRawX() - initialTouchX);
    params.y = initialY + (int) (event.getRawY() - initialTouchY);
    //Update the layout with new X & Y coordinate
    mWindowManager.updateViewLayout(mChatHeadView, params);
    return true;
    }
    break;
    }
    return true;
    }
    private boolean shouldClickActionWork(float startX, float endX, float startY, float endY) {
    float differenceX = Math.abs(startX - endX);
    float differenceY = Math.abs(startY - endY);
    if ((CLICK_ACTION_THRESHOLD > differenceX) && (CLICK_ACTION_THRESHOLD > differenceY))
    return true;
    else
    return false;
    }
    • ¿Qué es params ?
  9. 0

    Este es un ejemplo de TouchListener que no sombra ClickListener.

    import android.graphics.PointF
    import android.view.MotionEvent
    import android.view.MotionEvent.*
    import android.view.View
    import kotlin.math.abs
    object TouchAndClickListener : View.OnTouchListener {
    /** Those are factors you can change as you prefer */
    private const val touchMoveFactor = 10
    private const val touchTimeFactor = 200
    private var actionDownPoint = PointF(0f, 0f)
    private var previousPoint = PointF(0f, 0f)
    private var touchDownTime = 0L
    override fun onTouch(v: View, event: MotionEvent) = when (event.action) {
    ACTION_DOWN -> PointF(event.x, event.y).let {
    actionDownPoint = it  //Store it to compare position when ACTION_UP
    previousPoint = it  //Store it to compare position when ACTION_MOVE
    touchDownTime = now() //Store it to compare time when ACTION_UP
    /* Do other stuff related to ACTION_DOWN you may whant here */
    true
    }
    ACTION_UP -> PointF(event.x, event.y).let {
    val isTouchDuration = now() - touchDownTime < touchTimeFactor  //short time should mean this is a click
    val isTouchLength = abs(it.x - actionDownPoint.x) + abs(it.y - actionDownPoint.y) < touchMoveFactor  //short length should mean this is a click
    val shouldClick = isTouchLength && isTouchDuration  //Check both
    if (shouldClick) yourView.performClick() //Previously define setOnClickListener{ } on yourView, then performClick() will call it
    /* Do other stuff related to ACTION_UP you may whant here */
    true
    }
    ACTION_MOVE -> PointF(event.x, event.y).let {
    /* Do other stuff related to ACTION_MOVE you may whant here */
    previousPoint = it
    true
    }
    else -> false //Nothing particular with other event
    }
    private fun now() = System.currentTimeMillis()
    }

Dejar respuesta

Please enter your comment!
Please enter your name here