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.
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.
Nous allons ajouter le détecteur de geste à la variable verte View
.
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.
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