2017-01-20 3 views
1

J'ai trouvé une bonne classe d'écoute sur internet pour faire un OnSwipeTouchListener. Cet écouteur peut d'une durée déterminée lorsque l'utilisateur fait un simple glissement vers le bas, en haut, à gauche ou à droite:Faire la lettre L avec OnSwipeTouchListener

public class OnSwipeTouchListener implements View.OnTouchListener { 

    private GestureDetector gestureDetector; 

    protected OnSwipeTouchListener(Context c) { 
     gestureDetector = new GestureDetector(c, new GestureListener()); 
    } 

    public boolean onTouch(final View view, final MotionEvent motionEvent) { 
     return gestureDetector.onTouchEvent(motionEvent); 
    } 

    private final class GestureListener extends GestureDetector.SimpleOnGestureListener { 

     private static final int SWIPE_THRESHOLD = 100; 
     private static final int SWIPE_VELOCITY_THRESHOLD = 100; 

     @Override 
     public boolean onDown(MotionEvent e) { 
      return true; 
     } 

     @Override 
     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 
      try { 
       float diffY = e2.getY() - e1.getY(); 
       float diffX = e2.getX() - e1.getX(); 
       if (Math.abs(diffX) > Math.abs(diffY)) { 
        if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) { 
         if (diffX > 0) { 
          onSwipeRight(); 
         } else { 
          onSwipeLeft(); 
         } 
        } 
       } else { 
        if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) { 
         if (diffY > 0) { 
          onSwipeDown(); 
         } else { 
          onSwipeUp(); 
         } 
        } 
       } 
      } catch (Exception exception) { 
       exception.printStackTrace(); 
      } 
      return false; 
     } 
    } 

    public void onSwipeRight() { 
    } 

    public void onSwipeLeft() { 
    } 

    public void onSwipeUp() { 
    } 

    public void onSwipeDown() { 
    } 
} 

Voilà comment je l'utilise:

findViewById(R.id.framelayout).setOnTouchListener(new OnSwipeTouchListener(this) { 
      @Override 
      public void onSwipeDown() { 
       Toast.makeText(MainActivity.this, "Down", Toast.LENGTH_SHORT).show(); 
      } 

      @Override 
      public void onSwipeLeft() { 
       Toast.makeText(MainActivity.this, "Left", Toast.LENGTH_SHORT).show(); 
      } 

      @Override 
      public void onSwipeUp() { 
       Toast.makeText(MainActivity.this, "Up", Toast.LENGTH_SHORT).show(); 
      } 

      @Override 
      public void onSwipeRight() { 
       Toast.makeText(MainActivity.this, "Right", Toast.LENGTH_SHORT).show(); 
      } 
     }); 

Maintenant, je voudrais ajouter la fonction onSwipeL (). Cette fonction est quand l'utilisateur fait la lettre L avec le doigt, c'est comme onSwipeDown() + onSwipeRight().

Le meilleur serait de faire la fonction onSwipeDoubleL(). C'est quand l'utilisateur fait un double L inversé avec ses doigts. Il est comme en même temps à faire:

  • onSwipeDown() + onSwipeRight()
  • onSwipeDown() + onSwipeLeft()

Est-ce possible?

Répondre

0

Mais voici ma solution. Nous devrions attraper les événements tactiles, donc remplacer la méthode onTouchEvent. Là nous devons lire l'index des doigts qui sur l'écran maintenant.

Si nous avons plus d'une touche, appliquez l'index de droite pour le doigt qui coordonne X plus que le "doigt gauche". Je ne peux pas dire si je trouve des index corrects. Je vérifie donc les coordonnées des index. Dans l'étape suivante, nous sauvegardons le point de départ et commençons à descendre. Si nous avons 2 doigts sur l'écran, vérifiez les doigts droit et gauche sinon seulement à gauche (ou à droite comme vous le souhaitez). Si nous attrapons un événement lorsque la distance «descendante» est plus que minimale et que nous commençons à nous déplacer vers la gauche/droite, nous devons enregistrer un nouveau point de départ pour en calculer la distance.

Et attendez que l'utilisateur se déplace vers la gauche/droite avec une distance supérieure à min. Après tout, vérifiez le succès par "gauche" et "droite" des doigts ou tout simplement à gauche (une touche).

Nous devons également penser à l'inexactitude (erreurs, erreur) lors du déplacement. Les utilisateurs ne peuvent pas descendre ou rester parfaitement corrects, donc la solution dépend fortement de ce paramètre. Vous devez équilibrer les paramètres de portée et de précision pour faciliter le contrôle des gestes.

Le code n'est pas optimisé seulement montrer l'idée de base. Peut-être que vous trouverez plus petite solution. Je suis désolé pour mon niveau d'anglais

public class MainMenuActivity extends AppCompatActivity { 

    boolean movingDownL = false; 
    boolean movingDownR = false; 
    boolean movingLeft = false; 
    boolean movingRight = false; 

    boolean movingSuccessL = false; 
    boolean movingSuccessR = false; 

    // Deviation in pixels from the route (error value) 
    int downInaccuracy = 30; // Down 
    int lnrInaccuracy = 10; // Left and Right 

    // Minimum distance to apply move (300 px in down and 100 to the left/right) 
    int downMinDistance = 300; 
    int lnrMinDistance = 50; 

    Point oldCoordsL = new Point(0, 0); // Old coordinates left 
    Point oldCoordsR = new Point(0, 0); // Old coordinates right 
    Point startPointL = new Point(0, 0); 
    Point startPointR = new Point(0, 0); 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main_menu); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     int pIndexL = event.findPointerIndex(event.getPointerId(0)); 
     int pIndexR = 0; 

     // If we have more than 1 touch read second finger index 
     if(event.getPointerCount() > 1) pIndexR = event.findPointerIndex(event.getPointerId(1)); 

     // Check if we do not mistake when read fingers id 
     if(event.getPointerCount() > 1 && event.getX(pIndexL) > event.getX(pIndexR)) { 
      int tmp = pIndexR; 
      pIndexR = pIndexL; 
      pIndexL = tmp; 
     } 

     switch (event.getAction()) { 
      case MotionEvent.ACTION_DOWN: 
       movingDownL = true; // Start moving fingers 
       movingDownR = true; 
       movingSuccessL = false; 
       movingSuccessR = false; 

       // Get start point left and right if we need 
       if(event.getPointerCount() > 1) { 
        startPointR = new Point((int) event.getX(pIndexR), (int) event.getY(pIndexR)); 
        oldCoordsR = new Point((int) event.getX(pIndexR), (int) event.getY(pIndexR)); 
       } 

       startPointL = new Point((int) event.getX(pIndexL), (int) event.getY(pIndexL)); 
       oldCoordsL = new Point((int) event.getX(pIndexL), (int) event.getY(pIndexL)); 
       break; 
      case MotionEvent.ACTION_MOVE: 
       // Add right finger handler 
       if(event.getPointerCount() > 1) { 
        if(!movingDownR) { 
         // Check if we still moving to down 
         if(Math.abs(oldCoordsR.x - event.getX(pIndexR)) < downInaccuracy && 
           oldCoordsR.y < event.getY(pIndexR)) break; 
         // Start moving to the right 
         if(Math.abs(oldCoordsR.y - event.getY(pIndexR)) < lnrInaccuracy && 
           oldCoordsR.x > event.getX(pIndexR) && !movingRight) { 
          movingRight = true; 
          startPointR = new Point(new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR))); 
         } 
        }else { 
         if (Math.abs(oldCoordsR.x - event.getX(pIndexR)) > downInaccuracy || 
           oldCoordsR.y < event.getY(pIndexR)) { 
          movingDownR = false; 
          break; 
         } else if(findDistance(startPointR, 
           new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR))) >= downMinDistance){ 
          // Start moving to the left/right 
          movingDownR = false; 
         } 
        } 
       } 

       // Left finger handler by default even if we got only one touch 
       // Check if we need move to any side 
       if(!movingDownL) { 
        // Check if we still moving to down 
        if(Math.abs(oldCoordsL.x - event.getX(pIndexL)) < downInaccuracy && 
          oldCoordsL.y < event.getY(pIndexL)) break; 
        // Start moving to the left 
        if(Math.abs(oldCoordsL.y - event.getY(pIndexL)) < lnrInaccuracy && 
          oldCoordsL.x < event.getX(pIndexL) && !movingLeft) { 
         movingLeft = true; 
         startPointL = new Point(new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL))); 
        } 
       }else { 
        if (Math.abs(oldCoordsL.x - event.getX(pIndexL)) > downInaccuracy || 
          oldCoordsL.y > event.getY(pIndexL)) { 
         movingDownL = false; 
         break; 
        } else if(findDistance(startPointL, 
          new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL))) >= downMinDistance){ 
         // Start moving to the left/right 
         movingDownL = false; 
        } 
       } 

       // Left move handler 
       if(movingLeft) { 
        if (Math.abs(oldCoordsL.y - event.getY(pIndexL)) > lnrInaccuracy || 
          oldCoordsL.x > event.getX(pIndexL)) { 
         movingLeft = false; 
         break; 
        } else if(findDistance(startPointL, 
          new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL))) >= lnrMinDistance) { 
         movingLeft = false; 
         movingSuccessL = true; // L from left finger is OK 
        } 
       } 

       // Right move handler 
       if(movingRight) { 
        if (Math.abs(oldCoordsR.y - event.getY(pIndexR)) > lnrInaccuracy || 
          oldCoordsR.x < event.getX(pIndexR)) { 
         movingRight = false; 
         break; 
        } else if(findDistance(startPointR, 
          new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR))) >= lnrMinDistance) { 
         movingRight = false; 
         movingSuccessR = true; // L from right finger is OK 
        } 
       } 

       if(movingSuccessL && movingSuccessR) { 
        Toast.makeText(this, "Yeah, it's look like double L", Toast.LENGTH_SHORT).show(); 
       } else if(movingSuccessL) Toast.makeText(this, "Yeah, it's look like L", Toast.LENGTH_SHORT).show(); 

       oldCoordsL = new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL)); 
       oldCoordsR = new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR)); 

       break; 
      case MotionEvent.ACTION_UP: 
       movingDownL = false; 
       movingDownR = false; 
       movingLeft = false; 
       movingRight = false; 
       break; 
      default: 
       return false; 
     } 

     return true; 
    } 

    private double findDistance(Point p1, Point p2) { 
     return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)); 
    } 
} 
+0

J'ai le message "Ouais, ça ressemble à double L" tout le temps quand je touche l'écran. –

+0

C'est bizarre. J'ai testé l'application dans 2 appareils, tout fonctionne bien. Avez-vous copié mon code correctement? Ou changer quelque chose?Il ne peut pas faire de message avec le toucher car movingSuccessL et movingSuccessR sont toujours faux –

+0

Maintenant, cela fonctionne désolé. Le problème est: si je mets un débogage par exemple je vois plusieurs fois mon débogage quand je fais le double L. C'est un gros problème car il faut que j'appelle un fragment après ça et l'app appelle plusieurs fois ce fragment. Comment puis-je faire pour appeler seulement 1 fois? –

0

Il existe deux options.

  • Première utilisation de certains booléens. isSwipedRight (par exemple). Et vérifier onSwipeRight() si isSwipedDown vrai, si oui, puis faire des choses. Dans onSwipeDown(), définissez booléen sur true, dans tous les autres (sauf en bas) sur false.
  • Créez votre propre onTouchListener et mesurez les distances par vous-même. Je ne peux vraiment pas comprendre pourquoi vous avez besoin de ce geste.