Androïde SimpleOnGestureListener.onfling obtenir un null MotionEvent
j'essaie de détecter un événement fling sur une simple application Android, mais le premier MotionEvent
argument est toujours nul. Pourquoi la méthode onFling est-elle appelée avec un argument null? documentation Android dit qu'il est appelé quand un événement de fling se produit avec le MotionEvent initial on down et le MotionEvent correspondant vers le haut.
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;
}
}
l'activité principale a cette méthode onTouchEvent:
GestureDetector flingDetector = new GestureDetector(new MyGestureDetector());
@Override
public boolean onTouchEvent(MotionEvent event) {
if (flingDetector.onTouchEvent(event)) {
return true;
}
return super.onTouchEvent(event);
}
6 réponses
j'ai le même problème. Cela se produit lorsque le GestureDetector et la méthode onFling étaient dans une classe de vue personnalisée, qui fait partie de L'UI d'activité. Après une série de tests, j'ai constaté que seule l'activité principale peut bien détecter le geste de balayage. Donc je résous le problème en les remplaçant dans l'activité. Mais je n'ai pas trouvé la cause profonde de ce problème.
j'ai d'abord rencontré ce problème avec Android 4.0 que mon code fonctionne très bien dans toutes les versions antérieures. Après avoir pris un indice des suggestions ici, j'ai trouvé une solution facile est de garder une trace de l'événement onDown et de l'utiliser à la place du premier param de onFling au cas où il se trouve être 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
}
j'ai le même problème avec custom view et OnGestureListener onFling. Trouvé ceci:
que vous utilisiez ou non GestureDetector.SimpleOnGestureListener, toi doit toujours implémenter une méthode onDown() qui retourne true.
provenant de http://developer.android.com/training/custom-views/making-interactive.html
dans la classe custom view group vous devez outrepasser 2 méthodes:onInterceptTouchEvent
et onTouchEvent
. Après cela, vous devez appeler GestureDetector.onTouchEvent()
dans les deux méthodes. Événement ACTION_DOWN
est passé à onInterceptTouchEvent
uniquement.
@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);
}
j'ai eu 3 boutons en horizonal linéaire de la mise en page et cette mise en page, à son tour entouré par horizontalscrollview
.
Puis j'ai mis simplegesturelistener
sur le horizontalscrollview
et obtenu la même erreur que ci-dessus. Puis, j'ai aussi mis simplegesturelistener
pour tous les boutons de la mise en page et ça a marché.
je pense que l'événement onDown a été repris par le scrollview, donc nous ne pouvons pas obtenir l'événement dans l'activité. Si vous personnalisez un ScrollView et outrepassez les dispatchTouchEvent() et onTouchEvent(), le problème sera résolu.
Activité:
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
}
}
enfin, 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
}
Espérons que cette aide.