2012-07-10 22 views
17

Estoy intentando utilizar gestos dentro de un fragmento; Tengo lo siguiente dentro de FragmentActivity que maneja mi fragmento de detalles. Lo que intento que ocurra es cuando se detecta un deslizamiento en la vista para reemplazar los datos dentro de esa vista con la entrada anterior o siguiente.Fragmento de Android onCreateView con gestos

Si hay una mejor manera de manejar esto; Estoy totalmente de acuerdo. Sin embargo, lo que está sucediendo aquí es que el método onFling en realidad nunca se llama.

public static class DetailsFragment extends Fragment { 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 
     if (container == null) { 
      return null; 
     } 
     View v = inflater.inflate(R.layout.my_view, null, false); 
     final GestureDetector gesture = new GestureDetector(getActivity(), 
      new GestureDetector.SimpleOnGestureListener() { 
       @Override 
       public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 
        float velocityY) { 

        final int SWIPE_MIN_DISTANCE = 120; 
        final int SWIPE_MAX_OFF_PATH = 250; 
        final int SWIPE_THRESHOLD_VELOCITY = 200; 
        try { 
         if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) 
          return false; 
         if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE 
          && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
          Log.i(Constants.APP_TAG, "Right to Left"); 
         } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE 
          && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
          Log.i(Constants.APP_TAG, "Left to Right"); 
          titles.showDetails(getPosition() - 1); 
         } 
        } catch (Exception e) { 
         // nothing 
        } 
        return super.onFling(e1, e2, velocityX, velocityY); 
       } 
      }); 

     v.setOnTouchListener(new View.OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       return gesture.onTouchEvent(event); 
      } 
     }); 

     return v; 
    } 
} 

Respuesta

43

Parece que el problema siguiente explica esto: Android: GestureDetector won't catch Gestures

Además aquí está el resultado:

La solución es realmente reemplazar el método onDown y return true; de lo contrario el detector gesto se detendrá y no detecta el arriba:

 final GestureDetector gesture = new GestureDetector(getActivity(), 
      new GestureDetector.SimpleOnGestureListener() { 

       @Override 
       public boolean onDown(MotionEvent e) { 
        return true; 
       } 

       @Override 
       public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 
        float velocityY) { 
        Log.i(Constants.APP_TAG, "onFling has been called!"); 
        final int SWIPE_MIN_DISTANCE = 120; 
        final int SWIPE_MAX_OFF_PATH = 250; 
        final int SWIPE_THRESHOLD_VELOCITY = 200; 
        try { 
         if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) 
          return false; 
         if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE 
          && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
          Log.i(Constants.APP_TAG, "Right to Left"); 
         } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE 
          && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
          Log.i(Constants.APP_TAG, "Left to Right"); 
         } 
        } catch (Exception e) { 
         // nothing 
        } 
        return super.onFling(e1, e2, velocityX, velocityY); 
       } 
      }); 

     v.setOnTouchListener(new View.OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       return gesture.onTouchEvent(event); 
      } 
     }); 
+3

solo curiosidad: ¿por qué no se pierde la referencia al gesto? –

+1

@LemLordjeKo ¿por qué se va a perder la referencia a 'gesture'? 'gesture' se mantiene como referencia en el' View.OnTouchListener' que creamos, y se mantiene como referencia en la vista en sí, 'v'. Java es lo suficientemente maduro, si hay un camino hacia un objeto, es casi seguro que no se obtendrá GC. – bclymer

+0

Se necesitan las siguientes importaciones para que el fragmento de código anterior funcione: import android.view.View.OnTouchListener; import android.view.MotionEvent; import android.view.GestureDetector; import android.util.Log; constantes de clase { public static final Cadena APP_TAG = "mytag"; } – FuzzyAmi

2

un par de comentarios

  1. tuve que ajustar mi código de la siguiente manera:

    v.setOnTouchListener(new View.OnTouchListener() { 
        @Override   
        public boolean onTouch(View v, MotionEvent event) { 
    
         // return gesture.onTouchEvent(event); 
    
         gesture.onTouchEvent(event); 
         return true; // <-- this line made the difference 
        } 
    }); 
    
  2. Además, si están utilizando un archivo xml para crear su vista

    View v = inflater.inflate(R.layout.my_view, null, false); 
    

asegúrese de que está presionando la vista deseada. Una buena manera de exagerar la prueba es hacer que tanto el ancho como la altura sean "match_parent" en lugar de "wrap_content" en su archivo xml de diseño.

+0

Olvidé que @mwillbanks anula onDown para que sea verdadero para SimpleOnGestureListener. Solo implemente en onSingleTapConfirmed y onDoubleTap. – gnemnk

Cuestiones relacionadas