2011-03-12 35 views
15

Creé un widget/control que puedo reutilizar el cual creé extendiendo RelativeLayout. Luego, en una de mis actividades, creé un montón de estos widgets en un bucle. Sin embargo, me encontré con un problema cuando quería que cada widget respondiera con un clic.OnTouch funciona, pero OnClickListener no?

He encontrado que la fijación de OnTouchListener obras:

this.setOnTouchListener(new OnTouchListener(){ 
     public boolean onTouch(View arg0, MotionEvent arg1) { 
      //Triggers debug message 
     }  
    }); 

pero OnClickListener no:

this.setOnClickListener(new View.OnClickListener(){ 
     public void onClick(View v) { 
      //Doesn't trigger debug message 
     } 

    }); 

¿Por qué es esto?

+0

¿Desea agregar a ambos para el mismo objeto? –

+0

@ nicholas.hauschild - No, uno a la vez - comente el otro ... – tpow

+0

debe devolver True en el OnTouchListener para evitar que el evento se consuma. –

Respuesta

15

Aquí están algunas cosas a comprobar para asegurarse de que sus puntos de vista son seleccionables:

View.setClickable() 
View.setEnabled() 
View.setFocusable() 
View.setFocusableInTouchMode() 

Dependiendo del comportamiento exacto que esperan obtener, usted tendrá que configurar uno o más de los que sucesivamente. Debido a que está recibiendo eventos de Touch, supongo que debe configurar Click. Pero tendría que ver el código de creación de vista para estar seguro.

+2

Gracias por la respuesta. Intenté configurar todo esto para que fuera verdadero, pero no funcionó. – tpow

+0

Establecer mi diseño relativo extendido en "this.setClickable (true);" en realidad fue la respuesta. Estaba usando un mensaje de "Toast" como declaración de depuración en lugar de logcat. Resulta que estaba usando el objeto de contexto incorrecto. Gracias hermano ... – tpow

46

Debe asegurarse de que el TouchListener no 'consume' el evento táctil. Si devuelve true desde el método onTouch(), Android lo considerará consumido y no lo transmitirá a los otros manejadores táctiles (que supongo que incluirá ClickListener).

que debe hacer:

this.setOnTouchListener(new OnTouchListener(){ 
    public boolean onTouch(View arg0, MotionEvent arg1) { 
     //Triggers debug message 
     return false; 
    }  
}); 
14

¿Vuelve el valor booleano onTouch correctamente?

A partir de los documentos:

onTouch() - Esto devuelve un valor booleano para indicar si su oyente consume este evento . Lo importante es que este evento puede tener varias acciones que se suceden. Por lo tanto, si devuelve falso cuando se recibe el evento de acción inactiva , indica que no ha consumido el evento y tampoco están interesados ​​en las siguientes acciones de este evento. Por lo tanto, no se invocará para ninguna otra acción dentro del evento, como un gesto de dedo , o el eventual evento de acción .

EDITAR

encontrado la solución en este question y simplemente probé a mí mismo.

Necesita usar este return super.onTouchEvent(event); en su código onTouchEvent. Después de agregar esto, OnClickListener comenzó a funcionar.

+0

Interesante y bueno saber ... Sin embargo, cuando pruebo el onClick, comento el OnTouch – tpow

+0

@cinqoTimo: respuesta editada. Pruébelo y vea si funciona. – Abhinav

+1

Gracias por la actualización. Pero, no estoy seguro exactamente a qué te refieres. ¿Dónde en el evento táctil iría esto? Intenté reemplazar "return true" en mi OnTouchListener - El "evento" es un "MotionEvent" y la superclase no lo reconoce. – tpow

0

Si reemplaza el método onMotionEvent() por algún motivo y necesita devolver verdadero/falso en ese caso, puede activar manualmente la devolución de llamada OnClickListener() llamando a this.performClick() dentro del evento onMotionEvent() reemplazado antes de regresar verdadero/falso

4

Para realizar este retorno falsa en su onTouch() así:

this.setOnTouchListener(new OnTouchListener(){  
     public boolean onTouch(View arg0, MotionEvent arg1) { 
      return false; 
     }  
}); 
+0

, pero esto inhabilitaría su oyente ontouch ... esto sería lo mismo que eliminarlo de su aplicación. – Simon

0

Cuando necesite ambos eventos onClick y onTouch en el mismo punto de vista, utilizar un GestureDetector.

2

Puede Implementar un OnClickListener través onTouchListener:

webView.setOnTouchListener(new View.OnTouchListener() { 

     public final static int FINGER_RELEASED = 0; 
     public final static int FINGER_TOUCHED = 1; 
     public final static int FINGER_DRAGGING = 2; 
     public final static int FINGER_UNDEFINED = 3; 

     private int fingerState = FINGER_RELEASED; 


     @Override 
     public boolean onTouch(View view, MotionEvent motionEvent) { 

      switch (motionEvent.getAction()) { 

       case MotionEvent.ACTION_DOWN: 
        if (fingerState == FINGER_RELEASED) fingerState = FINGER_TOUCHED; 
        else fingerState = FINGER_UNDEFINED; 
        break; 

       case MotionEvent.ACTION_UP: 
        if(fingerState != FINGER_DRAGGING) { 
         fingerState = FINGER_RELEASED; 

         // Your onClick codes 

        } 
        else if (fingerState == FINGER_DRAGGING) fingerState = FINGER_RELEASED; 
        else fingerState = FINGER_UNDEFINED; 
        break; 

       case MotionEvent.ACTION_MOVE: 
        if (fingerState == FINGER_TOUCHED || fingerState == FINGER_DRAGGING) fingerState = FINGER_DRAGGING; 
        else fingerState = FINGER_UNDEFINED; 
        break; 

       default: 
        fingerState = FINGER_UNDEFINED; 

      } 

      return false; 
     } 
    }); 
Cuestiones relacionadas