Android SimpleOnGestureListener.onFling получает нулевой MotionEvent
Я пытаюсь обнаружить событие fling в простом приложении для Android, но первый аргумент MotionEvent
всегда равен нулю. Почему метод onFling вызывается с нулевым аргументом? Документация Android говорит, что она вызывается, когда происходит событие fling с начальным нажатием 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;
}
}
Основная операция имеет этот метод onTouchEvent:
GestureDetector flingDetector = new GestureDetector(new MyGestureDetector());
@Override
public boolean onTouchEvent(MotionEvent event) {
if (flingDetector.onTouchEvent(event)) {
return true;
}
return super.onTouchEvent(event);
}
Ответы
Ответ 1
У меня есть аналогичная проблема. Это происходит, когда GestureDetector и метод onFling находятся в пользовательском классе представления, который является частью пользовательского интерфейса активности. После серии тестов я обнаружил, что только основная активность может хорошо распознать жестом салфетки. Поэтому я решу проблему, заменяя их в своей деятельности. Но я не нашел основной причины этой проблемы.
Ответ 2
Я впервые столкнулся с этой проблемой с Android 4.0, так как мой код отлично работает во всех предыдущих версиях. После взятия подсказки из предложений здесь я нашел легкое обходное решение - просто следить за событием onDown и использовать его вместо первого параметра onFling, если он окажется нулевым.
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
}
Ответ 3
У меня такая же проблема с пользовательским представлением и OnGestureListener onFling. Обнаружили это:
Независимо от того, используете ли вы GestureDetector.SimpleOnGestureListener, вы должен всегда реализовывать метод onDown(), который возвращает true.
Получено из http://developer.android.com/training/custom-views/making-interactive.html
Ответ 4
В пользовательском классе группы просмотра вам нужно переопределить 2 метода: onInterceptTouchEvent
и onTouchEvent
. После этого вам нужно вызвать 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);
}
Ответ 5
У меня было 3 кнопки в горизонтальной линейной компоновке, и этот макет, в свою очередь, был окружен horizontalscrollview
.
Затем я установил simplegesturelistener
на horizontalscrollview
и получил ту же ошибку, что и выше. Затем я также установил simplegesturelistener
для всех кнопок в макете и работал.
Ответ 6
Я думаю, что событие 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
}
Надеюсь на эту помощь.