2011-03-09 3 views
1

J'essaie d'implémenter une vue qui a à la fois un longClickListener et un détecteur de mouvement. Fondamentalement, j'ai besoin d'un bouton pour afficher une vue lorsque l'utilisateur clique longtemps sur la première vue, puis je veux détecter un mouvement de lancement. Je voudrais faire en sorte que l'utilisateur n'a pas à lever le doigt du tout, et frapper à la fois le longclick, et le mouvement de lancer.Voir avec gesture listener et onLongClickListener

Voici mon code pour le longClickListener:

flipCard.setOnLongClickListener(new View.OnLongClickListener() { 
      public boolean onLongClick(View view) { 
        answerRight.setVisibility(View.VISIBLE); 
        answerRight.startAnimation(AnimationUtils.loadAnimation(view.getContext(), R.anim.grow_from_middle)); 
        answerWrong.setVisibility(View.VISIBLE); 
        answerWrong.startAnimation(AnimationUtils.loadAnimation(view.getContext(), R.anim.grow_from_middle)); 
        return false; 
      } 
     }); 

Voici le code pour mon geste Dector:

gestureDetectorScore = new GestureDetector(new ScoreGestureDetector()); 
    gestureListenerScore = new View.OnTouchListener() { 
     public boolean onTouch(View v, MotionEvent event) { 
      if (gestureDetectorScore.onTouchEvent(event)) { 
       return true; 
      } 
      return false; 
     } 
    }; 
private class ScoreGestureDetector extends SimpleOnGestureListener { 

    private static final int SWIPE_MIN_DISTANCE = 5; 
    private static final int SWIPE_THRESHOLD_VELOCITY = 2; 

    @Override 
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 
     try { 
       //if (Math.abs(e1.getX() - e2.getX()) > SWIPE_MAX_OFF_PATH) 
       //return false; 
       // right to left swipe 
       //if(e1.getY() - e2.getY() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
       if(e1.getY() - e2.getY() > SWIPE_MIN_DISTANCE){ 
       Toast.makeText(AndroidOrientationSensor.this, "Up Swipe", Toast.LENGTH_SHORT).show(); 
       } 
       //else if (e2.getY() - e1.getY() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
       else if (e2.getY() - e1.getY() > SWIPE_MIN_DISTANCE){ 
        Toast.makeText(AndroidOrientationSensor.this, "Down Swipe", Toast.LENGTH_SHORT).show(); 
       } 
      } catch (Exception e) { 
       // nothing 
      } 
      return false; 
    } 

    @Override 
    public boolean onDown(MotionEvent e1){ 
     Toast.makeText(AndroidOrientationSensor.this, "Up Swipe", Toast.LENGTH_SHORT).show(); 
     return true; 
    } 

} 

Enfin, je suis en train de le geste Dectector à la vue "Flipcard" comme ceci:

flipCard.setOnTouchListener(gestureListenerScore); 

Toute aide serait grandement appréciée.

Répondre

0

Ce que j'ai fini par faire pour résoudre ce problème est de placer un objet gestureDectector sur la vue et de surcharger la méthode onDown. Cela m'a permis de simuler un événement click. J'ai été incapable d'obtenir à la fois un clic long et un événement de balayage, mais pour mes fins, l'événement de clic se déclenche pendant le balayage qui semble fonctionner correctement. Merci à GauntFace pour l'inspiration.

0

Je pense que le problème que vous allez rencontrer est que si l'événement tactile est consommé par le bouton, la seconde vue ne le recevra pas.

Même si c'était le cas, le coup que j'imagine ne sera appelé que lorsque l'utilisateur effectuera une aventure du début à la fin.

La seule chose que je peux penser à faire (bien qu'il soit très horrible/hacky) est d'essayer d'insérer un faux événement tactile. Cela pourrait alors permettre à l'utilisateur d'effectuer le lancer, mais ce n'est pas particulièrement stable non plus. Une meilleure façon de le gérer serait d'avoir un groupe de vue consommer les événements tactiles, passer les événements tactiles à un détecteur de mouvement pour détecter un clic long, puis définir un drapeau dans les groupes de vue tactile d'écoute pour indiquer un fling est attendue, puis détecter manuellement lorsque prev y et current y dépassent un seuil. Cela vous donnera une idée de la vélocité mais probablement pas aussi significative que la vélocité fournie dans la méthode de rappel onFling.

+0

Bonne idée, j'ai beaucoup de mal à implémenter cela. J'essaye de recréer un longClickEvent dans l'écouteur de geste. En vérifiant les coordonnées pour s'assurer qu'elles correspondent avec le bouton, puis en simulant un long clic, je peux être capable d'attraper l'événement de fling. –

+0

Malheureusement, parce que vous voulez que tout se passe dans un seul événement tactile, il ne sera pas facile de le faire. Tout ce que je peux dire est à partir de votre code actuel, plutôt que de passer le GestureDetector dans setOnTouchListener, vous pouvez remplacer la méthode onTouchEvent, puis retourner mGestureDetector.onTouchEvent (motionEvent); évidemment avec ceci, après un long clic vous pouvez vous-même acheter les touchesvents et faire ce que vous voulez avec eux (c'est-à-dire détecter un fling personnalisé) –

0

Le GestureListener a également un événement onLongPress.

+0

C'est vrai, mais l'événement est consommé, et n'attrape pas l'événement fling. C'est en fait assez intéressant, car pour attraper un événement onLongPress, vous devez d'abord attraper l'événement onDown. L'api déclare que "tous les autres événements devraient être précédés de ceci". De plus, les événements onLongPress consomment toujours l'événement, ce qui annulerait l'événement de lancement. voir http://developer.android.com/reference/android/view/GestureDetector.SimpleOnGestureListener.html#onLongPress(android.view.MotionEvent) –