Android SimpleOnGestureListener.onFling obtener un objeto nulo MotionEvent

Estoy tratando de detectar un evento de fling en una simple aplicación de Android, pero el primer argumento de MotionEvent siempre es nulo. ¿Por qué se llama al método onFling con un argumento nulo? La documentación de Android dice que se llama cuando se produce un evento de fling con la inicial en abajo MotionEvent y la coincidencia de MotionEvent.

 class MyGestureDetector extends SimpleOnGestureListener { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // e1 always == null, return early a null reference exception if (e1 == null) { return false; } if (e1.getY() - e2.getY() > 120) { handleFlingEvent(); return true; } return false; } } 

La actividad principal tiene este método onTouchEvent:

 GestureDetector flingDetector = new GestureDetector(new MyGestureDetector()); @Override public boolean onTouchEvent(MotionEvent event) { if (flingDetector.onTouchEvent(event)) { return true; } return super.onTouchEvent(event); } 

Tengo el problema similar. Sucede cuando el método GestureDetector y el método onFling se encontraban en una clase de vista personalizada, que forma parte de la interfaz de usuario de la actividad. Después de una serie de pruebas encontré que sólo la actividad principal puede detectar el gesto de deslizamiento también. Así que solucionar el problema por sustituirlos en la actividad. Pero no encontré la causa raíz de este problema.

En primer lugar me encontré con este problema con Android 4.0 como mi código funciona bien en todas las versiones anteriores. Después de tomar una señal de las sugerencias aquí, he encontrado una solución fácil es sólo realizar un seguimiento del evento onDown y utilizarlo en lugar del primer parámetro de onFling en caso de que suceda a ser nulo.

 public class MySimpleGestureListener extends SimpleOnGestureListener { protected MotionEvent mLastOnDownEvent = null; @Override public boolean onDown(MotionEvent e) { mLastOnDownEvent = e; return true;//super.onDown(e); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (e1==null) e1 = mLastOnDownEvent; if (e1==null || e2==null) return false; float dX = e2.getX()-e1.getX(); float dY = e2.getY()-e1.getY(); ...rest of code } ...rest of class } 

Tengo el mismo problema con la vista personalizada y OnGestureListener onFling. Encontré esto:

Sea o no utilizar GestureDetector.SimpleOnGestureListener, siempre debe implementar un método onDown () que devuelve true.

Sourced de http://developer.android.com/training/custom-views/making-interactive.html

Tenía 3 botones en el diseño lineal horizontal y esta disposición a su vez rodeada por horizontalscrollview .

Entonces simplegesturelistener el simplegesturelistener en el horizontalscrollview y conseguí el mismo error que arriba. Entonces también simplegesturelistener para todos los botones en el diseño y trabajó.

Creo que el evento onDown ha sido reanudado por el scrollview, por lo que no podemos obtener el evento en la actividad. Si personaliza un ScrollView y reemplaza el dispatchTouchEvent () y onTouchEvent (), el problema se resolverá.

Actividad:

 public class TestActivity extends Activity { private MyScrollView scrollView; private TestActivity me; private GestureDetector detector; protected void onCreate(Bundle savedInstanceState) { this.me = this; MySimpleGestureListener gestureListener = new MySimpleGestureListener(); this.detector = new GestureDetector(gestureListener); this.scrollView.setOnTouchListener(onTouchListerner); this.scrollView.setDetector(detector); } private View.OnTouchListener onTouchListener = new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return me.detector.onTouchEvent(event); } }; } 

MySimpleGestureListener:

 public class MySimpleGestureListener extends SimpleOnGestureListener { @Override public boolean onSingleTapUp(MotionEvent e) { return false; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return super.onScroll(e1, e2, distanceX, distanceY); } @Override public void onLongPress(MotionEvent e) { } @Override public boolean onDown(MotionEvent e) { return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO do your onFling here } } 

Por fin, MyScrollView

 public class MyScrollView extends ScrollView { private GestureDetector detector; @Override public boolean dispatchTouchEvent(MotionEvent ev){ if (this.detector!= null) { detector.onTouchEvent(ev); super.dispatchTouchEvent(ev); return true; } return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent ev) { super.onTouchEvent(ev); // if (this.detector != null) { return this.detector.onTouchEvent(ev); } return false; } // here is the getter and setter } 

Espero que esto ayude.

En la clase de grupo de vista personalizada, necesita los métodos override 2: onInterceptTouchEvent y onTouchEvent . Después de eso, debe llamar a GestureDetector.onTouchEvent() en ambos métodos. El evento ACTION_DOWN se pasa a onInterceptTouchEvent solamente.

 @Override public boolean onInterceptTouchEvent(MotionEvent event) { if(mDetector.onTouchEvent(event)) { return true; } return super.onInterceptTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { if(mDetector.onTouchEvent(event)) { return true; } return super.onTouchEvent(event); } 
  • Android - ImageView en el clic
  • Evento de Android Touch en la pantalla
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.