Gérer les gestes tactiles multipoints

Essayer Compose
Jetpack Compose est le kit d'outils d'interface utilisateur recommandé pour Android. Découvrez comment utiliser l'écran tactile et la saisie dans Compose.
<ph type="x-smartling-placeholder"></ph> Gestes à plusieurs doigts →

Un geste multipoint consiste à appuyer sur l'écran avec plusieurs pointeurs (doigts) en même temps. Ce document explique comment détecter les gestes impliquant plusieurs pointeurs.

Suivre plusieurs pointeurs

Lorsque plusieurs pointeurs appuient sur l'écran en même temps, le système génère les événements tactiles suivants:

  • ACTION_DOWN: envoyé lorsque le premier pointeur appuie sur l'écran. Le geste est alors déclenché. La les données de ce pointeur se trouvent toujours à l'index 0 dans le MotionEvent
  • ACTION_POINTER_DOWN: envoyé lorsque des pointeurs supplémentaires arrivent à l'écran après le premier. Vous pouvez obtenir l'index du pointeur qui vient de descendre en utilisant getActionIndex()
  • ACTION_MOVE: lorsqu'un changement se produit dans un geste, impliquant n'importe quel nombre ces pointeurs.
  • ACTION_POINTER_UP: envoyé lorsqu'un pointeur non principal apparaît. Vous pouvez obtenir l'index du pointeur qui vient de monter à l'aide de getActionIndex().
  • ACTION_UP: envoyé lorsque le dernier pointeur quitte l'écran.
  • ACTION_CANCEL: indique que l'ensemble du geste, y compris tous les pointeurs, est annulé.

Gestes de début et de fin

Un geste est une série d'événements commençant par un ACTION_DOWN et se terminant par un ACTION_UP ou ACTION_CANCEL. Il y a un geste actif à la fois. La les actions BAS, DÉPLACER, MONTER et ANNULER s'appliquent à l'ensemble du geste. Par exemple, un un événement avec ACTION_MOVE peut indiquer un mouvement pour tous les pointeurs à ce moment-là.

Garder une trace des pointeurs

Utiliser l'index et l'ID du pointeur pour effectuer le suivi des pointeurs individuels dans une MotionEvent.

  • Index: une MotionEvent stocke un pointeur dans un tableau. L'index d'un pointeur correspond à sa position dans ce tableau. La plupart des méthodes MotionEvent utilisent l'index de pointeur comme un paramètre plutôt que l'ID de pointeur.
  • ID: chaque pointeur possède également un mappage d'ID qui reste persistant entre les événements tactiles pour permettre le suivi d'un pointeur individuel ; tout au long du geste.

Les pointeurs individuels apparaissent dans un événement de mouvement dans un ordre indéterminé. Ainsi, l'index d'un pointeur peut changer d'un événement à l'autre, mais l'identifiant du pointeur d'un pointeur reste constant tant qu'il reste actif. Utilisez les getPointerId() pour obtenir l'identifiant d'un pointeur afin de le suivre sur toutes les les événements de mouvement dans un geste. Ensuite, pour des événements de mouvement successifs, utilisez la findPointerIndex() pour obtenir l'index de pointeur pour un ID de pointeur donné dans cet événement de mouvement. Exemple :

Kotlin

private var mActivePointerId: Int = 0

override fun onTouchEvent(event: MotionEvent): Boolean {
    ...
    // Get the pointer ID.
    mActivePointerId = event.getPointerId(0)

    // ... Many touch events later...

    // Use the pointer ID to find the index of the active pointer
    // and fetch its position.
    val (x: Float, y: Float) = event.findPointerIndex(mActivePointerId).let { pointerIndex ->
        // Get the pointer's current position.
        event.getX(pointerIndex) to event.getY(pointerIndex)
    }
    ...
}

Java

private int mActivePointerId;

public boolean onTouchEvent(MotionEvent event) {
    ...
    // Get the pointer ID.
    mActivePointerId = event.getPointerId(0);

    // ... Many touch events later...

    // Use the pointer ID to find the index of the active pointer
    // and fetch its position.
    int pointerIndex = event.findPointerIndex(mActivePointerId);
    // Get the pointer's current position.
    float x = event.getX(pointerIndex);
    float y = event.getY(pointerIndex);
    ...
}

Pour prendre en charge plusieurs pointeurs tactiles, vous pouvez mettre en cache tous les pointeurs actifs avec leurs identifiants au niveau de leur ACTION_POINTER_DOWN individuel ; Heure de l'événement ACTION_DOWN. Supprimez les pointeurs de votre cache sur ses événements ACTION_POINTER_UP et ACTION_UP. Vous pourriez trouver ces ID mis en cache utiles pour gérer correctement les autres événements d'action. Pour Par exemple, lors du traitement d'un événement ACTION_MOVE, recherchez l'index chaque ID de pointeur actif mis en cache, récupérez ses coordonnées à l'aide de la méthode getX() et getY() fonctions, puis comparez ces coordonnées à celles de votre compte identifier les pointeurs qui ont été déplacés.

Utiliser la fonction getActionIndex() avec ACTION_POINTER_UP et ACTION_POINTER_DOWN événements uniquement. N'utilisez pas cette fonction avec les événements ACTION_MOVE, car cela renvoie toujours 0.

Récupérer MotionEvent actions

Utilisez les getActionMasked() ou la version de compatibilité MotionEventCompat.getActionMasked() pour récupérer l'action d'un MotionEvent. Contrairement à la précédente getAction() , getActionMasked() est conçu pour fonctionner avec plusieurs ces pointeurs. Elle renvoie l'action sans les index de pointeur. Pour les actions associées à un index de pointeur valide, utilisez getActionIndex() pour renvoyer l'index de les pointeurs associés à l'action, comme indiqué dans l'extrait suivant:

<ph type="x-smartling-placeholder">

Kotlin

val (xPos: Int, yPos: Int) = MotionEventCompat.getActionMasked(event).let { action ->
    Log.d(DEBUG_TAG, "The action is ${actionToString(action)}")
    // Get the index of the pointer associated with the action.
    MotionEventCompat.getActionIndex(event).let { index ->
        // The coordinates of the current screen contact, relative to
        // the responding View or Activity.
        MotionEventCompat.getX(event, index).toInt() to MotionEventCompat.getY(event, index).toInt()
    }
}

if (event.pointerCount > 1) {
    Log.d(DEBUG_TAG, "Multitouch event")

} else {
    // Single touch event.
    Log.d(DEBUG_TAG, "Single touch event")
}

...

// Given an action int, returns a string description.
fun actionToString(action: Int): String {
    return when (action) {
        MotionEvent.ACTION_DOWN -> "Down"
        MotionEvent.ACTION_MOVE -> "Move"
        MotionEvent.ACTION_POINTER_DOWN -> "Pointer Down"
        MotionEvent.ACTION_UP -> "Up"
        MotionEvent.ACTION_POINTER_UP -> "Pointer Up"
        MotionEvent.ACTION_OUTSIDE -> "Outside"
        MotionEvent.ACTION_CANCEL -> "Cancel"
        else -> ""
    }
}

Java

int action = MotionEventCompat.getActionMasked(event);
// Get the index of the pointer associated with the action.
int index = MotionEventCompat.getActionIndex(event);
int xPos = -1;
int yPos = -1;

Log.d(DEBUG_TAG,"The action is " + actionToString(action));

if (event.getPointerCount() > 1) {
    Log.d(DEBUG_TAG,"Multitouch event");
    // The coordinates of the current screen contact, relative to
    // the responding View or Activity.
    xPos = (int)MotionEventCompat.getX(event, index);
    yPos = (int)MotionEventCompat.getY(event, index);

} else {
    // Single touch event.
    Log.d(DEBUG_TAG,"Single touch event");
    xPos = (int)MotionEventCompat.getX(event, index);
    yPos = (int)MotionEventCompat.getY(event, index);
}
...

// Given an action int, returns a string description
public static String actionToString(int action) {
    switch (action) {

        case MotionEvent.ACTION_DOWN: return "Down";
	case MotionEvent.ACTION_MOVE: return "Move";
	case MotionEvent.ACTION_POINTER_DOWN: return "Pointer Down";
	case MotionEvent.ACTION_UP: return "Up";
	case MotionEvent.ACTION_POINTER_UP: return "Pointer Up";
	case MotionEvent.ACTION_OUTSIDE: return "Outside";
	case MotionEvent.ACTION_CANCEL: return "Cancel";
    }
    return "";
}
<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
Figure 1 : Dessin multipoint modèles de ML.

Ressources supplémentaires

Pour en savoir plus sur les événements d'entrée, consultez les ressources suivantes : références: