Android SimpleOnGestureListener.onFling获取一个null的MotionEvent

我想在一个简单的Android应用程序中检测到一个抛出事件,但是第一个MotionEvent参数总是为空。 为什么用空参数调用onFling方法? Android的文档说,当一个闪光的事件发生与最初的向下MotionEvent和匹配的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; } } 

主Activity有这个onTouchEvent方法:

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

Solutions Collecting From Web of "Android SimpleOnGestureListener.onFling获取一个null的MotionEvent"

我有类似的问题。 当GestureDetector和onFling方法位于自定义视图类中(这是活动UI的一部分)时,会发生这种情况。 经过一系列的testing,我发现只有主要的Activity才能很好地检测到滑动手势。 所以我通过在活动中取代他们来解决问题。 但是我没有find这个问题的根源。

我首先遇到Android 4.0的这个问题,因为我的代码在以前的所有版本中工作正常。 从这里的build议中得到一个提示后,我发现一个简单的解决方法是跟踪onDown事件,并使用它来代替onFling的第一个参数,以防碰巧是null。

 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 } 

我有自定义视图和OnGestureListener onFling相同的问题。 发现这个:

无论您是否使用GestureDetector.SimpleOnGestureListener,都必须实现一个返回true的onDown()方法。

来自http://developer.android.com/training/custom-views/making-interactive.html

在自定义视图组类中,您需要重写2个方法: onInterceptTouchEventonTouchEvent 。 之后,您需要在两种方法中调用GestureDetector.onTouchEvent() 。 事件ACTION_DOWN仅传递给onInterceptTouchEvent

 @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); } 

我在水平线性布局中有3个button,而这个布局又被horizontalscrollview包围。

然后,我在simplegesturelistener上设置了simplegesturelistener ,并得到了与上面相同的错误。 然后,我也为布局中的所有button设置simplegesturelistener ,它的工作。

我认为onDown事件已经被scrollview恢复了,所以我们不能在活动中获取事件。 如果您自定义ScrollView并重写dispatchTouchEvent()和onTouchEvent(),则问题将得到解决。

活动:

 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 } } 

最后是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 } 

希望这个帮助。