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);
}
17
demandé sur mcrumley 2010-11-11 07:35:15

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.

2
répondu Cable W 2011-01-08 08:57:08

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
}
12
répondu Uncle Code Monkey 2017-01-13 15:45:24

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

5
répondu Olga 2012-11-12 10:43:45

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);
}
3
répondu OlegKrikun 2016-02-05 16:30:25

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é.

2
répondu Namit Rana 2012-07-18 12:31:09

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.

0
répondu KeithKnight 2013-10-16 09:00:07