2013-02-08 3 views
24

Voici mon code, je veux détecter quand mon doigt descend de l'écran alors quand je touche l'écran, je détecte le ACTION_DOWN mais quand je descends l'écran avec mon doigt, ACTION_MOVE n'est pas reconnu, ni ACTION_UP Savez-vous Pourquoi?Android: OnTouch, MotionEvent.ACTION_MOVE n'est pas reconnu?

 float x=0; 
protected void onCreate(Bundle savedInstanceState) { 
     do things 

     ImageView image2 = (ImageView) findViewById(R.id.imageView3); 
     image2.setOnTouchListener(new OnTouchListener(){ 

     @Override 
     public boolean onTouch(View arg0, MotionEvent arg1) { 
      if (arg1.getAction()==MotionEvent.ACTION_DOWN) { 

       x=arg1.getX(); 
      } 
      else { 
       if (arg1.getAction()==MotionEvent.ACTION_MOVE){ 
        if (arg1.getX()>x) { 
        do things 
        } 
       } 
       else { 
        if (arg1.getAction()==MotionEvent.ACTION_UP){ 
         do things 
        } 
       } 
      } 
} 
+3

Tout comme un point de vue général, vous avez beaucoup d'inutile d'autre s/ifs dans votre code. C'est beaucoup plus facile à lire et fonctionne de la même manière, si vous nettoyez certains d'entre eux. – Nathaniel

Répondre

81

Si votre onTouch() méthode retourne false en réponse à la ACTION_DOWN initiale MotionEvent, il ne recevra aucun des événements ultérieurs qui appartiennent à ce geste particulier. Au lieu de cela, ces événements tactiles seront présentés au parent dans la hiérarchie.

Pour phrase une autre façon, si vous revenez false de onTouch() pendant le début d'un geste (le ACTION_DOWN), il signale que la méthode ne veut plus voir plus du geste, et que les événements du geste devrait aller au parent View.

Comme markproxy souligne dans les commentaires ci-dessous, retour false lorsque le MotionEvent est autre chose qu'un ACTION_DOWN, comme un ACTION_MOVE par exemple, ne pas empêcher MotionEvent ultérieurs s dans le geste en cours d'être présenté au View.

+0

un grand merci juste ajouté retour vrai après le mouvement d'action et l'action vers le bas! – morg

+3

Je crois qu'un léger raffinement est nécessaire pour que cette réponse soit correcte. Si vous renvoyez 'false' de' onTouch() '_lorsque le' MotionEvent' est un événement 'ACTION_DOWN', il signale que' View' ne veut plus voir le geste et que les événements du geste devraient aller à le parent 'ViewGroup'. Renvoyer 'false' d'un événement' ACTION_MOVE', par exemple, n'empêchera pas les événements futurs d'être acheminés vers cette 'View'. – markproxy

+0

@markproxy Mille mercis - J'ai mis à jour la réponse et j'espère l'avoir rendue plus précise. – Trevor

8

MotionEvent.getAction() retours plus que le drapeau. Effectuez les opérations suivantes:

int action = arg1.getAction() & MotionEvent.ACTION_MASK; 
if (action == MotionEvent.ACTION_MOVE) ... 

Vous pouvez également utiliser MotionEvent.getActionMasked(). Voir aussi http://developer.android.com/reference/android/view/MotionEvent.html

+0

Je ne comprends pas la différence entre getAction et getActionMasked même en lisant l'API? J'ai essayé l'action int = arg1.getAction() & MotionEvent.ACTION_MASK, ne fonctionnait pas – morg

+4

getAction() renvoie également un index de pointeur (vous en avez seulement besoin lorsque vous traitez plusieurs événements tactiles), donc vous ne pouvez pas utiliser en toute sécurité == les drapeaux mais doivent utiliser le masque ou appeler getActionMasked(). – Thalur

4

deux choses:

1) Vous devez retourner un booléen pour vous montrer que vous êtes vue consommé de l'événement.

Voici une très simple application qui fonctionne: méthode

package com.test; 

import android.app.Activity; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.View.OnTouchListener; 

public class TestProjActivity extends Activity { 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     final String TAG = "TEST_TAG"; 
     View v = findViewById(R.id.touchTest); 
     v.setOnTouchListener(new OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 

        if (event.getAction()==MotionEvent.ACTION_DOWN) { 

         Log.e(TAG,"Down"); 
         return true; 
        } 

        if (event.getAction()==MotionEvent.ACTION_MOVE){ 

         Log.e(TAG,"Move"); 
         return true; 

        } 
        if (event.getAction()==MotionEvent.ACTION_UP){ 

         Log.e(TAG,"Up"); 
         return true; 
        } 


        return false; 
      } 
     }); 
    } 
} 

Voici le main.xml

::

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical" > 

    <TextView 
     android:id="@+id/touchTest" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:text="@string/hello" /> 

</LinearLayout> 
2

Vérifiez la valeur de retour de OnTouch().

ce devrait être vrai, pas faux.

return true; 

espérons que cela fonctionnera.

2

Il y a deux cas:

1) Si vous définissez également OnClickListener() -> OnTouch() devrait renvoyer false.

(Si OnTouch() retourne true, OnClickListener() ne fonctionnera pas)

2) Si vous ne définissez pas OnClickListener() -> OnTouch() doit retourner vrai.

(Si OnTouch() retourne false, seul ACTION_DOWN est appelé)