OnFling MotionEvent e1 null?
De acuerdo. Esta cosa casi me vuelve loco.
Hace unos días pude implementar el código de abajo y el brindis fue llamado con éxito cuando intenté deslizar hacia la derecha o hacia la izquierda.
Sin embargo, ahora no se puede llamar, porque el e1 siempre es nulo!
¿Cómo pudo pasar esto? Intento este código en el emulador, pero un usuario me informa, que también no funciona en el dispositivo real.
public class SwipeGestureListener extends GestureDetector.SimpleOnGestureListener{ private static final int SWIPE_MIN_DISTANCE = 150; private static final int SWIPE_MAX_OFF_PATH = 100; private static final int SWIPE_THRESHOLD_VELOCITY = 100; private final Activity activity; protected MotionEvent mLastOnDownEvent = null; public SwipeGestureListener(Activity activity) { this.activity = activity; } @Override public boolean onDown(MotionEvent e) { mLastOnDownEvent = e; System.out.println(e); return super.onDown(e); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { System.out.println(e1 + " " + e2); if (e1==null) e1 = mLastOnDownEvent; if (e1==null || e2==null) return false; float dX = e2.getX()-e1.getX(); float dY = e2.getY()-e1.getY(); if (Math.abs(dY)<SWIPE_MAX_OFF_PATH && Math.abs(velocityX)>=SWIPE_THRESHOLD_VELOCITY && Math.abs(dX)>=SWIPE_MIN_DISTANCE ) { if (dX>0) { Toast.makeText(activity.getApplicationContext(), "Right Swipe", Toast.LENGTH_SHORT).show(); activity.fetchPrevious(); } else { Toast.makeText(activity.getApplicationContext(), "Left Swipe", Toast.LENGTH_SHORT).show(); activity.fetchNext(); } return true; } return false; } }
El código que implementa el gesto:
final GestureDetector gdt = new GestureDetector(this, new SwipeGestureListener(this)); listview.setOnTouchListener(new OnTouchListener(){ @Override public boolean onTouch(View v, MotionEvent event) { gdt.onTouchEvent(event); return false; } });
Intenté su código y de hecho no trabajó, después cambié el GestureDetector a la API más nueva / actualizada "GestureDetectorCompat" y cambié algunas cosas más: Utilizado el GestureDetector.OnGestureListener en vez del OnSimpleGestureListener, onDown () debe devolver verdadero y Entonces funcionó. No puedo explicarle a usted, cuál era el problema exacto. Pero las líneas de cambio parecían ser problemáticas. Tal vez alguien puede explicar el problema subyacente. Echa un vistazo al código, que está funcionando:
public class MainActivity extends Activity { ImageView imageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView= (ImageView) findViewById(R.id.imageView1); final GestureDetectorCompat gdt = new GestureDetectorCompat(this, new SwipeGestureListener(this)); imageView.setOnTouchListener(new OnTouchListener(){ @Override public boolean onTouch(View v, MotionEvent event) { return gdt.onTouchEvent(event); } }); } public class SwipeGestureListener implements GestureDetector.OnGestureListener{ private static final int SWIPE_MIN_DISTANCE = 150; private static final int SWIPE_MAX_OFF_PATH = 100; private static final int SWIPE_THRESHOLD_VELOCITY = 100; private final Activity activity; protected MotionEvent mLastOnDownEvent = null; public SwipeGestureListener(Activity activity) { this.activity = activity; } @Override public boolean onDown(MotionEvent e) { mLastOnDownEvent = e; System.err.println("ondown"); //System.out.println(e); return true; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { System.err.println("onFling"); System.out.println(e1 + " " + e2); if (e1==null) e1 = mLastOnDownEvent; if (e1==null || e2==null) return false; float dX = e2.getX()-e1.getX(); float dY = e2.getY()-e1.getY(); if (Math.abs(dY)<SWIPE_MAX_OFF_PATH && Math.abs(velocityX)>=SWIPE_THRESHOLD_VELOCITY && Math.abs(dX)>=SWIPE_MIN_DISTANCE ) { if (dX>0) { Toast.makeText(activity.getApplicationContext(), "Right Swipe", Toast.LENGTH_SHORT).show(); // activity.fetchPrevious(); } else { Toast.makeText(activity.getApplicationContext(), "Left Swipe", Toast.LENGTH_SHORT).show(); // activity.fetchNext(); } return true; } return false; } @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // TODO Auto-generated method stub return false; } @Override public void onShowPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return false; } } }
¡Por favor pruebalo!
Yo tuve el mismo problema. Si hay un onclicklistener etc que son swiping elementos, debe quitar a los oyentes. Entonces funcionará. Gracias..
Tuve un problema similar y lo resolví mediante la adición de un FrameLayout junto con la vista necesaria (estaba usando un GridView, pero creo que puede funcionar con un ListView u otra vista)
GestureListener es el mismo que el tuyo. El diseño:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout android:id="@+id/colors_grid_panel" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/white" android:paddingLeft="@dimen/create_side_padding" android:paddingRight="@dimen/create_side_padding" android:visibility="gone"> <GridView android:id="@+id/colors_grid" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:numColumns="7" android:paddingBottom="10dp" android:paddingTop="10dp" android:stretchMode="columnWidth" android:verticalSpacing="10dp"/> <FrameLayout android:id="@+id/stub" android:focusable="false" android:focusableInTouchMode="false" android:layout_width="match_parent" android:layout_height="match_parent"/> </FrameLayout>
En codigo:
colorsGrid.setOnTouchListener(onSwipeTouchListener); stub.setOnTouchListener(onSwipeTouchListener);
Yo tuve el mismo problema. Asegúrese de que todas sus vistas tienen agregar el mismo método setOnTouchListener()
. Si su lugar del tacto está fuera de la visión usted conseguirá null
en e1.
Mi ejemplo:
private View.OnTouchListener onTouchListener = new OnSwipeTouchListener(mActivity) { @Override public boolean onTouch(View v, MotionEvent event) { return super.onTouch(v, event); } @Override public void onSwipeLeft() { } @Override public void onSwipeRight() { } }; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //Inflate the layout for this fragment View v = inflater.inflate(R.layout.view, container, false); mListView = (ListView) v.findViewById(R.id.list); v.setFocusableInTouchMode(true); v.requestFocus(); v.setOnTouchListener(onTouchListener); mListView.setOnTouchListener(onTouchListener); mAdapter = new OnlineAdapter(getActivity(), R.layout.row, onTouchListener); mListView.setAdapter(mAdapter); return v; }
Y mi adaptador de lista:
@Override public View getView(final int position, View convertView, ViewGroup parent) { // something mImage = (ImageView) convertView.findViewById(R.id.image); mImage.setOnTouchListener(onTouchListener); }