web-dev-qa-db-fra.com

Comment ajouter un détecteur de geste à une vue sous Android

J'avais du mal à ajouter un détecteur de geste à une sous-vue de mon projet. Est-ce que je remplace la onTouchEvent du parent ou la onTouchEvent de l'enfant? Est-ce que je crée une OnTouchListener et y ajoute le détecteur de gestes? La documentation montre un exemple expliquant comment ajouter un détecteur de mouvements à l'activité elle-même, mais comment l'ajouter à une vue n'est pas claire. Le même processus pourrait être utilisé si vous sous-classiez une vue (exemple ici ), mais je veux ajouter le geste sans rien sous-classer.

Ceci est l’autre question la plus proche que j’ai pu trouver mais elle est spécifique à un geste de jet sur une ImageView, pas au cas général de toute View. Il y a aussi un certain désaccord dans ces réponses sur le moment de retourner true ou false

Pour m'aider à comprendre comment cela fonctionne, j'ai réalisé un projet autonome. Ma réponse est ci-dessous.

12
Suragch

Cet exemple montre comment ajouter un détecteur de mouvements à une vue. La mise en page est juste une View unique à l'intérieur d'une activité. Vous pouvez utiliser la même méthode pour ajouter un détecteur de mouvements à n’importe quel type de vue.

 enter image description here

Nous allons ajouter le détecteur de geste à la variable verte View.

MainActivity.Java

L'idée de base est d'ajouter un OnTouchListener à la vue. Normalement, nous obtiendrions ici toutes les données tactiles brutes (telles que ACTION_DOWN, ACTION_MOVE, ACTION_UP, etc.), mais au lieu de les traiter nous-mêmes, nous les transmettrons à un détecteur de mouvements pour interpréter les données tactiles.

Nous utilisons un SimpleOnGestureListener . La bonne chose à propos de ce détecteur de gestes est qu’il nous suffit de remplacer les gestes dont nous avons besoin. Dans l'exemple ici, j'en ai inclus beaucoup. Vous pouvez supprimer ceux dont vous n'avez pas besoin. (Cependant, vous devriez toujours renvoyer true dans onDown(). Renvoyer true signifie que nous traitons l'événement. Renvoyer false fera que le système cesse de nous donner d'autres événements tactiles.)

public class MainActivity extends AppCompatActivity {

    private GestureDetector mDetector;

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

        // this is the view we will add the gesture detector to
        View myView = findViewById(R.id.my_view);

        // get the gesture detector
        mDetector = new GestureDetector(this, new MyGestureListener());

        // Add a touch listener to the view
        // The touch listener passes all its events on to the gesture detector
        myView.setOnTouchListener(touchListener);
    }

    // This touch listener passes everything on to the gesture detector.
    // That saves us the trouble of interpreting the raw touch events 
    // ourselves.
    View.OnTouchListener touchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // pass the events to the gesture detector
            // a return value of true means the detector is handling it
            // a return value of false means the detector didn't 
            // recognize the event
            return mDetector.onTouchEvent(event);

        }
    };

    // In the SimpleOnGestureListener subclass you should override 
    // onDown and any other gesture that you want to detect.
    class MyGestureListener extends GestureDetector.SimpleOnGestureListener {

        @Override
        public boolean onDown(MotionEvent event) {
            Log.d("TAG","onDown: ");

            // don't return false here or else none of the other 
            // gestures will work
            return true;
        }

        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            Log.i("TAG", "onSingleTapConfirmed: ");
            return true;
        }

        @Override
        public void onLongPress(MotionEvent e) {
            Log.i("TAG", "onLongPress: ");
        }

        @Override
        public boolean onDoubleTap(MotionEvent e) {
            Log.i("TAG", "onDoubleTap: ");
            return true;
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, 
                                float distanceX, float distanceY) {
            Log.i("TAG", "onScroll: ");
            return true;
        }

        @Override
        public boolean onFling(MotionEvent event1, MotionEvent event2,
                               float velocityX, float velocityY) {
            Log.d("TAG", "onFling: ");
            return true;
        }
    }
}

C'est une configuration rapide pour exécuter ce projet, je vous recommande donc de l'essayer. Notez comment et quand les événements de journal se produisent.

28
Suragch

version courte en kotlin pour détecter le double tap uniquement pour une vue:

val gestureDetector = GestureDetector(activity, object : GestureDetector.SimpleOnGestureListener() {
    override fun onDoubleTap(e: MotionEvent?): Boolean {
        Log.d("myApp", "double tap")
        return true
    }
})
myView.setOnTouchListener { _, event -> gestureDetector.onTouchEvent(event) }

et n'oubliez pas de rendre myView cliquable

1
Palejandro