Cette leçon explique comment suivre les mouvements lors des événements tactiles.
Un nouveau onTouchEvent()
est déclenché avec un événement ACTION_MOVE
chaque fois que la position, la pression ou la taille actuelles du contact tactile change. Comme décrit dans la section Détecter les gestes courants, tous ces événements sont enregistrés dans le paramètre MotionEvent
de onTouchEvent()
.
Étant donné que la pression tactile n'est pas toujours la forme d'interaction la plus précise, la détection des événements tactiles est souvent davantage basée sur le mouvement que sur un simple contact. Pour aider les applications à faire la distinction entre les gestes basés sur le mouvement (comme un balayage) et les gestes qui ne bougent pas (comme un appui unique), Android inclut la notion de pente tactile. La pente tactile correspond à la distance en pixels que l'utilisateur peut parcourir avant que le geste ne soit interprété comme un geste basé sur un mouvement. Pour en savoir plus à ce sujet, consultez Gérer les événements tactiles dans un ViewGroup.
Il existe plusieurs façons de suivre les mouvements dans un geste, en fonction des besoins de votre application. Voici des exemples:
- Les positions de début et de fin d'un pointeur, par exemple le déplacement d'un objet à l'écran d'un point A à un point B.
- Direction dans laquelle se déplace le pointeur, telle que déterminée par les coordonnées X et Y.
- Historique. Vous pouvez trouver la taille de l'historique d'un geste en appelant la méthode
MotionEvent
getHistorySize()
. Vous pouvez ensuite obtenir les positions, les tailles, la durée et les pressions de chacun des événements historiques à l'aide des méthodesgetHistorical<Value>
des événements de mouvement. L'historique est utile lors de l'affichage d'une trace du doigt de l'utilisateur, par exemple pour le dessin tactile. Pour en savoir plus, consultez la documentation de référence surMotionEvent
. - Vitesse du pointeur lorsqu'il se déplace sur l'écran tactile.
Consultez les ressources associées suivantes :
- Présentation des événements d'entrée
- Présentation des capteurs
- Rendre une vue personnalisée interactive
Suivre la vitesse
Vous pouvez effectuer un geste basé sur le mouvement en fonction de la distance ou de la direction du pointeur. Cependant, la vitesse est souvent un facteur déterminant dans le suivi des caractéristiques d'un geste ou dans le choix de l'existence d'un geste. Pour faciliter le calcul de la vitesse, Android fournit la classe VelocityTracker
.
VelocityTracker
vous aide à suivre la vitesse des événements tactiles. Cela est utile pour les gestes dont la vitesse fait partie des critères du geste, tels qu'un glissement d'un geste vif.
Voici un exemple illustrant l'objectif des méthodes de l'API VelocityTracker
:
Kotlin
private const val DEBUG_TAG = "Velocity" class MainActivity : Activity() { private var mVelocityTracker: VelocityTracker? = null override fun onTouchEvent(event: MotionEvent): Boolean { when (event.actionMasked) { MotionEvent.ACTION_DOWN -> { // Reset the velocity tracker back to its initial state. mVelocityTracker?.clear() // If necessary, retrieve a new VelocityTracker object to watch // the velocity of a motion. mVelocityTracker = mVelocityTracker ?: VelocityTracker.obtain() // Add a user's movement to the tracker. mVelocityTracker?.addMovement(event) } MotionEvent.ACTION_MOVE -> { mVelocityTracker?.apply { val pointerId: Int = event.getPointerId(event.actionIndex) addMovement(event) // When you want to determine the velocity, call // computeCurrentVelocity(). Then, call getXVelocity() and // getYVelocity() to retrieve the velocity for each pointer // ID. computeCurrentVelocity(1000) // Log velocity of pixels per second. It's best practice to // use VelocityTrackerCompat where possible. Log.d("", "X velocity: ${getXVelocity(pointerId)}") Log.d("", "Y velocity: ${getYVelocity(pointerId)}") } } MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { // Return a VelocityTracker object back to be re-used by others. mVelocityTracker?.recycle() mVelocityTracker = null } } return true } }
Java
public class MainActivity extends Activity { private static final String DEBUG_TAG = "Velocity"; ... private VelocityTracker mVelocityTracker = null; @Override public boolean onTouchEvent(MotionEvent event) { int index = event.getActionIndex(); int action = event.getActionMasked(); int pointerId = event.getPointerId(index); switch(action) { case MotionEvent.ACTION_DOWN: if(mVelocityTracker == null) { // Retrieve a new VelocityTracker object to watch the // velocity of a motion. mVelocityTracker = VelocityTracker.obtain(); } else { // Reset the velocity tracker back to its initial state. mVelocityTracker.clear(); } // Add a user's movement to the tracker. mVelocityTracker.addMovement(event); break; case MotionEvent.ACTION_MOVE: mVelocityTracker.addMovement(event); // When you want to determine the velocity, call // computeCurrentVelocity(). Then call getXVelocity() and // getYVelocity() to retrieve the velocity for each pointer ID. mVelocityTracker.computeCurrentVelocity(1000); // Log velocity of pixels per second. It's best practice to use // VelocityTrackerCompat where possible. Log.d("", "X velocity: " + mVelocityTracker.getXVelocity(pointerId)); Log.d("", "Y velocity: " + mVelocityTracker.getYVelocity(pointerId)); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: // Return a VelocityTracker object back to be re-used by others. mVelocityTracker.recycle(); break; } return true; } }
Utiliser la capture du pointeur
Certaines applications, telles que les jeux, le bureau à distance et les clients de virtualisation, peuvent bénéficier du contrôle du pointeur de la souris. La capture du pointeur est une fonctionnalité disponible sur Android 8.0 (niveau d'API 26) ou version ultérieure qui fournit cette commande en diffusant tous les événements de souris dans une vue ciblée de votre application.
Demander la capture du pointeur
Une vue de votre application ne peut demander la capture du pointeur que si la hiérarchie des vues qui la contient est sélectionnée. Pour cette raison, demandez la capture du pointeur en cas d'action utilisateur spécifique sur la vue, par exemple lors d'un événement onClick()
ou dans le gestionnaire d'événements onWindowFocusChanged()
de votre activité.
Pour demander la capture du pointeur, appelez la méthode requestPointerCapture()
sur la vue. L'exemple de code suivant montre comment demander la capture du pointeur lorsque l'utilisateur clique sur une vue:
Kotlin
fun onClick(view: View) { view.requestPointerCapture() }
Java
@Override public void onClick(View view) { view.requestPointerCapture(); }
Une fois que la requête de capture du pointeur aboutit, Android appelle onPointerCaptureChange(true)
.
Le système envoie les événements de souris à la vue sélectionnée de votre application tant qu'elle se trouve dans la même hiérarchie que la vue qui a demandé la capture. Les autres applications cessent de recevoir les événements de souris jusqu'à ce que la capture soit libérée, y compris les événements ACTION_OUTSIDE
. Android transmet normalement les événements de pointeur provenant de sources autres que la souris, mais le pointeur de la souris n'est plus visible.
Gérer les événements de pointeur capturés
Une fois qu'une vue acquiert la capture du pointeur, Android envoie les événements de souris. Votre vue ciblée peut gérer les événements en effectuant l'une des tâches suivantes:
- Si vous utilisez une vue personnalisée, remplacez
onCapturedPointerEvent(MotionEvent)
. - Sinon, enregistrez un
OnCapturedPointerListener
.
L'exemple de code suivant montre comment implémenter onCapturedPointerEvent(MotionEvent)
:
Kotlin
override fun onCapturedPointerEvent(motionEvent: MotionEvent): Boolean { // Get the coordinates required by your app. val verticalOffset: Float = motionEvent.y // Use the coordinates to update your view and return true if the event is // successfully processed. return true }
Java
@Override public boolean onCapturedPointerEvent(MotionEvent motionEvent) { // Get the coordinates required by your app. float verticalOffset = motionEvent.getY(); // Use the coordinates to update your view and return true if the event is // successfully processed. return true; }
L'exemple de code suivant montre comment enregistrer un OnCapturedPointerListener
:
Kotlin
myView.setOnCapturedPointerListener { view, motionEvent -> // Get the coordinates required by your app. val horizontalOffset: Float = motionEvent.x // Use the coordinates to update your view and return true if the event is // successfully processed. true }
Java
myView.setOnCapturedPointerListener(new View.OnCapturedPointerListener() { @Override public boolean onCapturedPointer (View view, MotionEvent motionEvent) { // Get the coordinates required by your app. float horizontalOffset = motionEvent.getX(); // Use the coordinates to update your view and return true if the event is // successfully processed. return true; } });
Que vous utilisiez une vue personnalisée ou que vous enregistriez un écouteur, votre vue reçoit un MotionEvent
avec des coordonnées de pointeur qui spécifient des mouvements relatifs, tels que les deltas X ou Y, semblables aux coordonnées fournies par un trackball. Vous pouvez récupérer les coordonnées à l'aide de getX()
et de getY()
.
Libérer la capture du pointeur
La vue de votre application peut libérer la capture du pointeur en appelant releasePointerCapture()
, comme illustré dans l'exemple de code suivant:
Kotlin
override fun onClick(view: View) { view.releasePointerCapture() }
Java
@Override public void onClick(View view) { view.releasePointerCapture(); }
Le système peut retirer la capture de la vue sans que vous ayez explicitement appelé releasePointerCapture()
, généralement parce que la hiérarchie des vues contenant la vue qui demande la capture perd son focus.