Voy a comentar los pasos que he realizado para resolver esto ya que estuve varios días con dolores de cabeza por esto y en internet la información que encontraba era un poco oscura y muy difícil de adaptar a mi código.
Lo que mi aplicación tiene es un ViewFlipper y dentro de él hay 3 RelativeLayout y 1 ScrollView, tal que así:
- Código: Seleccionar todo
<ViewFlipper>
<RelativeLayout 1 ... />
<RelativeLayout 2 ... />
<RelativeLayout 3 ... />
<ScrollView ... />
</ViewFlipper>
Y lo que yo pretendo hacer es que, mediante el deslizado horizontal del dedo sobre la pantalla, me cambie de un RelativeLayout a otro o al ScrollView y viceversa. Para cambiar de un RelativeLayout a otro no existe problema, el problema llega cuando es del ScrollView al RelativeLayout, ya que la pantalla de ScrollView captura el evento de los gestos con el dedo.
Para los movimientos entre RelativeLayouts, declaramos la clase MyGestureDetector, que heredará de SimpleOnGestureListener, necesaria para capturar el evento de movimiento con el dedo mediante el método onFling(...).
- Código: Seleccionar todo
public class TuActivity implements OnClickListener {
// ...
private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
private GestureDetector gestureDetector = null;
View.OnTouchListener gestureListener = null;
class MyGestureDetector extends SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
try {
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
desliza(e1, e2, velocityX, velocityY, vf);
} catch (Exception e) {
// nothing
}
return false;
}
}
// Procedimiento encargado de hacer la animación cuando se captura
// el movimiento del dedo
public void desliza(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY, ViewFlipper vfpr){
if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY)
moverDerecha(TuActivity.this, vfpr);
else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY)
moverIzquierda(TuActivity.this, vfpr);
}
// Mover a la pantalla siguiente
public void moverDerecha(Context c, ViewFlipper vfp){
vfp.setInAnimation(c, tu_animacion);
vfp.setOutAnimation(c, tu_animacion);
vfp.showNext();
}
// Mover a la pantalla anterior
public void moverIzquierda(Context c, ViewFlipper vfp){
vfp.setInAnimation(c, tu_animacion);
vfp.setOutAnimation(c, tu_animacion);
vfp.showPrevious();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (gestureDetector.onTouchEvent(event))
return true;
else
return false;
}
Ahora bien, en el método onCreate(...) hacemos lo siguiente:
- Código: Seleccionar todo
@Override
public void onCreate(Bundle savedInstanceState) {
// ...
gestureDetector = new GestureDetector(new MyGestureDetector());
gestureListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
};
vf = (ViewFlipper) findViewById(R.id.desliza);
vf.setOnTouchListener(gestureListener);
// ...
}
Pues bien, después de muchos quebraderos de cabeza y días de trabajo perdidos, un día se me ocurrió copiar y pegar este mismo código y en el onCreate(...) asignárselo al ScrollView sv en vez de como hice antes con el ViewFlipper vf. Por tanto, lo que hice fue:
- Replicar la variable gestureDetector como gestureSDetector
- Replicar la variable gestureListener como gestureSListener
- Replicar la clase MyGestureDetector como MyScrollGestureDetector. El método onFling(...) permanecerá exactamente igual.
- Replicar lo que escribí antes en el método onCreate(...) pero en este caso con gestureSDetector, gestureSListener y ScrollView sv.
Al final, el método onCreate(...) quedaría así:
- Código: Seleccionar todo
@Override
public void onCreate(Bundle savedInstanceState) {
// ...
gestureDetector = new GestureDetector(new MyGestureDetector());
gestureListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
};
vf = (ViewFlipper) findViewById(R.id.viewflipper);
vf.setOnTouchListener(gestureListener);
gestureSDetector = new GestureDetector(new MyScrollGestureDetector());
gestureSListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureSDetector.onTouchEvent(event);
}
};
sv = (ScrollView) findViewById(R.id.scrollview);
sv.setOnTouchListener(gestureSListener);
Solucionado, se acabó el problema de por qué el ScrollView no funcionaba con el movimiento en horizontal del dedo.
Un saludo, espero que les sirva de ayuda y les ahorre gran cantidad de tiempo.
