2011-08-02 11 views
6

Tengo un Gallery completa de ImageView s, y los ImageView s son pinch-zoom y traducible. Mi objetivo es que una vez que ImageView ya no se pueda traducir a la izquierda/derecha, el Gallery se desplazará. Por lo tanto, a veces el ImageView necesita manejar el evento táctil, a veces el Gallery necesita manejar el evento táctil. Tengo la lógica en mi onTouchEvent método ImageView 's para cuando quiero que la mano-off que se produzca, pero estoy obteniendo resultados inesperados. Voy a explicar el problema después de muestro mi código:torpe la propagación de eventos contacto entre las vistas

// PinchZoomImageView.java 

@Override 
public boolean onTouchEvent(MotionEvent event) { 

    Log.i("PinchZoomImageView", "IM GETTING TOUCHED!"); 

    if (isPassThroughTouchEvent()) { 
     Log.i("PinchZoomImageView", "IM RETURNING FALSE!"); 
     return false; 
    } 

    getScaleDetector().onTouchEvent(event); 

    switch (event.getAction() & MotionEvent.ACTION_MASK) { 
     case MotionEvent.ACTION_DOWN: { 
      final float x = event.getX(); 
      final float y = event.getY(); 

      setLastTouchX(x); 
      setLastTouchY(y); 
      setActivePointerId(event.getPointerId(0)); 

      break; 
     } 

     case MotionEvent.ACTION_MOVE: { 
      final int pointerIndex = event.findPointerIndex(getActivePointerId()); 
      final float x = event.getX(pointerIndex); 
      final float y = event.getY(pointerIndex); 

      // Only move if the ScaleGestureDetector isn't processing a gesture. 
      if (!getScaleDetector().isInProgress()) { 
       if (isDetectMovementX()) { 
        final float dx = x - getLastTouchX(); 
        setPosX(getPosX() + dx); 
       } 

       if (isDetectMovementY()) { 
        final float dy = y - getLastTouchY(); 
        setPosY(getPosY() + dy); 
       } 

       invalidate(); 
      } 

      setLastTouchX(x); 
      setLastTouchY(y); 

      if (isAtXBound() && !isPassThroughTouchEvent()) { 

       setPassThroughTouchEvent(true); 
      } 

      break; 
     } 

     case MotionEvent.ACTION_UP: { 
      setActivePointerId(INVALID_POINTER_ID); 
      break; 
     } 

     case MotionEvent.ACTION_CANCEL: { 
      setActivePointerId(INVALID_POINTER_ID); 
      break; 
     } 

     case MotionEvent.ACTION_POINTER_UP: { 
      final int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; 
      final int pointerId = event.getPointerId(pointerIndex); 
      if (pointerId == getActivePointerId()) { 
       // This was our active pointer going up. Choose a new 
       // active pointer and adjust accordingly. 
       final int newPointerIndex = pointerIndex == 0 ? 1 : 0; 
       setLastTouchX(event.getX(newPointerIndex)); 
       setLastTouchY(event.getY(newPointerIndex)); 
       setActivePointerId(event.getPointerId(newPointerIndex)); 
      } 
      break; 
     } 
    } 

    return true; 
} 

y mi Gallery aquí. Sobreescribí onTouchEvent solo para mostrar cuándo estaba recibiendo eventos táctiles.

// SwipeGallery.java 

@Override 
public boolean onTouchEvent(MotionEvent event) { 

    Log.i("SwipeGallery", "IM GETTING TOUCHED!"); 
    return super.onTouchEvent(event); 
} 

Así que cuando cargo la actividad, intento deslizarme de derecha a izquierda. La lógica para pasar el evento de movimiento se activa de inmediato, pero aquí está mi salida de registro.

08-02 10:04:47.097: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 
08-02 10:04:47.179: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 
08-02 10:04:47.179: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 
08-02 10:04:47.179: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 
08-02 10:04:47.230: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 
08-02 10:04:47.230: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 
08-02 10:04:47.230: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 
08-02 10:04:47.230: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 
08-02 10:04:47.245: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 
08-02 10:04:47.245: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 
08-02 10:04:47.261: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 
08-02 10:04:47.261: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 
08-02 10:04:47.277: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 
08-02 10:04:47.277: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 
08-02 10:04:47.296: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 
08-02 10:04:47.296: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 
08-02 10:04:47.312: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 
08-02 10:04:47.312: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 
08-02 10:04:47.327: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 
08-02 10:04:47.327: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 
08-02 10:04:47.343: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 
08-02 10:04:47.343: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 
08-02 10:04:47.360: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 
08-02 10:04:47.360: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 
....etc. 

la segunda vez que deslice de derecha a izquierda, me sale esto:

08-02 10:27:31.573: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 
08-02 10:27:31.573: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 
08-02 10:27:31.573: INFO/SwipeGallery(17189): IM GETTING TOUCHED! 
08-02 10:27:31.636: INFO/SwipeGallery(17189): IM GETTING TOUCHED! 
08-02 10:27:31.636: INFO/SwipeGallery(17189): IM GETTING TOUCHED! 
08-02 10:27:31.683: INFO/SwipeGallery(17189): IM GETTING TOUCHED! 
08-02 10:27:31.933: INFO/SwipeGallery(17189): IM GETTING TOUCHED! 
08-02 10:27:31.964: INFO/SwipeGallery(17189): IM GETTING TOUCHED! 
08-02 10:27:31.999: INFO/SwipeGallery(17189): IM GETTING TOUCHED! 
08-02 10:27:32.034: INFO/SwipeGallery(17189): IM GETTING TOUCHED! 

Este patrón de "evento de movimiento primero el imageview maneja siempre, segundo evento de movimiento la galería maneja siempre" continúa para siempre (Se realiza una nueva vista de la imagen para cada posición en la galería, por lo que isPassThroughTouchEvent() devuelve falso la 3ª, 5ª, etc.). Entonces, ¿qué es exactamente lo que me falta aquí? Pensé que devolver falso propagaría el evento táctil hasta que se manejara, pero el Gallery no lo tomará la primera vez, pero sí el segundo. Esto no tiene ningún sentido para mí. ¿Alguien tiene alguna idea? Gracias.

+0

¿Has probado clearFocus() en la galería? – bgs

+0

Me gustaría mantener un enfoque de abajo hacia arriba donde 'ImageView' y' Gallery' no saben que existen y no es necesario. Además, cualquier acción tomada en la 'Galería' no afectará mi primer resultado de barrido donde la' Galería' nunca recibe ningún evento táctil. –

+0

Soy curioso cómo solucionar esto, ¿Cómo es isPassThroughTouchEvent()? – bgs

Respuesta

3

Cuando una vista devuelve verdadero en el evento de movimiento hacia abajo (ACTION_DOWN), que vista está "bloqueado en" como el destino del movimiento táctil. Lo que significa que recibirá los eventos de movimiento posteriores hasta el evento final hasta independientemente de donde se sucede en la pantalla (ver este thread), a menos que si su matriz wants y allowed para interceptar el evento.

para explicar su situación:

  1. En el primer golpe, su ImageView maneja el movimiento hacia abajo que hace que sea el destino del movimiento (véase el registro). Eso significa que todos los eventos de movimiento posteriores serán entregados a él, y desde su Gallery no intercepta los eventos, su manejador onTouchEvent no será llamado.

  2. En el segundo golpe, su ImageView no manejan el movimiento hacia abajo (como se muestra en el registro con "IM TOQUE haciendo!" + "IM devolver false!") Y se pasó el caso al siguiente gestor, en este caso el Gallery que ejecutará su controlador onTouchEvent. Por defecto, Gallery maneja siempre el evento hacia abajo, que lo bloquea como el objetivo de movimiento.

+0

Así que he intentado reenviar un 'MotionEvent' cambiando la acción a' ACTION_DOWN' a través de 'MotionEvent.obtain (MotionEvent)' y 'dispatchTouchEvent (MotionEvent)' con el mismo resultado. El evento se envía a 'onTouchEvent (MotionEvent)) de mi ImageView, he verificado que es una acción inactiva y devuelve falso, con los mismos resultados que se muestran arriba. –

+0

Volver a enviar un 'MotionEvent' no cambiará nada. Una vez que una vista se ha convertido en un objetivo de movimiento (al manejar el evento hacia abajo) se bloqueará como objetivo de movimiento hasta el evento final, a menos que el padre lo intercepte. Lo que debe verificar es por qué su 'isPassThroughTouchEvent()' devuelve verdadero en el segundo deslizamiento. –

+0

Porque lo configuré en verdadero. Mire dentro de la caja por 'ACTION_MOVE' en la parte inferior. El booleano se establece exactamente cuando lo necesito, así que no es el problema. Básicamente necesito una forma de liberar el "bloqueo" que tiene mi vista de imagen en el evento táctil cuando ese valor booleano se establece en verdadero. –

Cuestiones relacionadas