Utiliser les mouvements du poignet sur Wear
Restez organisé à l'aide des collections
Enregistrez et classez les contenus selon vos préférences.
Les mouvements du poignet vous permettent d'interagir d'une seule main avec votre application lorsqu'il n'est pas facile d'utiliser l'écran tactile.
Par exemple, un utilisateur peut faire défiler les notifications avec une main tout en tenant un verre d'eau dans l'autre. Voici d'autres cas d'utilisation des mouvements du poignet :
- Dans une application de jogging, vous pouvez parcourir les écrans verticaux qui indiquent le nombre de pas effectués, le temps écoulé et l'allure actuelle.
- Dans une application de voyage, vous pouvez faire défiler les informations sur les vols et les portes d'embarquement.
- Dans une application d'actualités, vous pouvez faire défiler les articles.
Pour vérifier les fonctionnalités associées aux mouvements du poignet sur votre montre, confirmez que les gestes sont activés en accédant à Paramètres > Fonctionnalités avancées > Gestes > Mouvements du poignet. Effectuez ensuite le tutoriel sur les gestes en sélectionnant Lancer le tutoriel.
Remarque : Secouer le poignet est le geste d'annulation ou de retour pour tout le système. Ce geste ne peut pas être personnalisé pour une application.
Les mouvements du poignet peuvent être utilisés des manières suivantes, comme décrit dans ce guide :
Chaque mouvement du poignet est mappé à une constante int
de la classe KeyEvent
, comme indiqué dans le tableau suivant :
Geste
|
KeyEvent
|
Description
|
Tournez le poignet vers l'extérieur.
|
KEYCODE_NAVIGATE_NEXT
|
Ce code de clavier permet de passer à l'élément suivant.
|
Tournez le poignet vers l'intérieur.
|
KEYCODE_NAVIGATE_PREVIOUS
|
Ce code de clavier permet de passer à l'élément précédent.
|
Utiliser une mise en page incurvée pour permettre les mouvements du poignet
La classe
WearableRecyclerView
offre une mise en page incurvée pour les listes et accepte automatiquement les mouvements du poignet. Elle comporte des actions prédéfinies pour les mouvements du poignet lorsque la vue est ciblée. Pour en savoir plus sur l'utilisation de la classe WearableRecyclerView
, consultez Créer des listes sur Wear OS. Consultez également la section Bonnes pratiques de ce guide.
Remarque : La classe WearableRecyclerView
remplace une classe similaire obsolète de la bibliothèque Wearable Support.
Même si vous utilisez une propriété WearableRecyclerView
, vous pouvez vous servir des constantes de la classe KeyEvent
. Les actions prédéfinies peuvent être remplacées en sous-classant WearableRecyclerView
et en implémentant de nouveau le rappel onKeyDown()
. Vous pouvez désactiver entièrement ce comportement à l'aide de setEnableGestureNavigation(false)
.
Pour en savoir plus, consultez Gérer les actions du clavier.
Utiliser des événements de touche directement
Pour déclencher de nouvelles actions en réponse à des événements gestuels, vous pouvez utiliser des événements de touche en dehors d'un
WearableRecyclerView
. Il est important de noter que ces événements gestuels sont reconnus lorsqu'un appareil est en mode Actif. Ils sont diffusés de la même manière que tous les événements de touche.
Une classe liée à l'interaction de l'utilisateur, comme View
ou Activity
, et qui implémente
KeyEvent.Callback
peut écouter les événements de touche liés aux mouvements du poignet comme tout autre événement de touche. Le framework Android appelle le View
ou l'Activity
ciblés avec les événements de touche. Pour les gestes, le rappel de la méthode onKeyDown()
est appelé lorsque des gestes se produisent.
Par exemple, une application peut ignorer des actions prédéfinies dans un View
ou un Activity
implémentant KeyEvent.Callback
comme suit :
Kotlin
class GesturesActivity : Activity() {
/* KeyEvent.Callback */
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
return when (keyCode) {
KeyEvent.KEYCODE_NAVIGATE_NEXT ->
// Do something that advances a user View to the next item in an ordered list.
moveToNextItem()
KeyEvent.KEYCODE_NAVIGATE_PREVIOUS ->
// Do something that advances a user View to the previous item in an ordered list.
moveToPreviousItem()
else -> {
// If you did not handle it, let it be handled by the next possible element as determined
// by the Activity.
super.onKeyDown(keyCode, event)
}
}
}
/** Shows the next item in the custom list. */
private fun moveToNextItem(): Boolean {
...
// Return true if handled successfully, otherwise return false.
return false
}
/** Shows the previous item in the custom list. */
private fun moveToPreviousItem(): Boolean {
...
// Return true if handled successfully, otherwise return false.
return false
}
}
Java
public final class GesturesActivity extends Activity {
@Override /* KeyEvent.Callback */
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_NAVIGATE_NEXT:
// Do something that advances a user View to the next item in an ordered list.
return moveToNextItem();
case KeyEvent.KEYCODE_NAVIGATE_PREVIOUS:
// Do something that advances a user View to the previous item in an ordered list.
return moveToPreviousItem();
}
// If you did not handle it, let it be handled by the next possible element as determined by the Activity.
return super.onKeyDown(keyCode, event);
}
/** Shows the next item in the custom list. */
private boolean moveToNextItem() {
boolean handled = false;
...
// Return true if handled successfully, otherwise return false.
return handled;
}
/** Shows the previous item in the custom list. */
private boolean moveToPreviousItem() {
boolean handled = false;
...
// Return true if handled successfully, otherwise return false.
return handled;
}
}
Bonnes pratiques
- Examinez les pages
KeyEvent
et
KeyEvent.Callback
concernant la diffusion des événements de touche pour vos View
et Activity
.
- Assurez-vous de proposer une affordance directionnelle cohérente : si la rotation de poignet vers l'extérieur est utilisée pour passer à l'élément suivant, la rotation vers l'intérieur peut faire passer à l'élément précédent.
- Effectuez une pression en parallèle pour un geste.
- Fournissez des commentaires visuels.
- N'utilisez pas de code de clavier pour implémenter une fonctionnalité qui serait contre-intuitive par rapport au reste du système. Par exemple, n'utilisez pas
KEYCODE_NAVIGATE_NEXT
pour annuler une action ou parcourir l'axe de gauche à droite à l'aide d'une rotation du poignet.
- N'interceptez pas les événements de touche au niveau d'éléments qui ne font pas partie de l'interface utilisateur, tels que les vues qui sont hors de l'écran ou partiellement couvertes. C'est la même chose que pour un événement de touche.
- Ne réinterprétez pas les mouvements du poignet répétés dans un geste inédit qui vous est propre.
Il risque de créer en conflit avec le geste "Secouer le poignet" utilisé au niveau du système.
Pour qu'une vue reçoive des événements gestuels de touche, elle doit être ciblée. Consultez la section consacrée à
View.setFocusable()
.
Étant donné que les gestes sont traités comme des événements de touche, ils déclenchent une transition qui quitte le "mode tactile" et qui peut donc entraîner des actions inattendues. Comme les utilisateurs peuvent alterner entre l'écran tactile et les gestes, la méthode
View::setFocusableInTouchmode()
peut être requise. Dans certains cas, il peut également être nécessaire d'utiliser setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS)
pour que la vue souhaitée soit sélectionnée lorsque le ciblage passe d'un mode à l'autre (mode tactile ou gestes).
- Attention à l'utilisation de
requestFocus()
et de clearFocus()
:
- Lorsque vous appelez la méthode
requestFocus()
, assurez-vous qu'elle est appropriée pour cibler la vue. Si la vue se trouve hors de l'écran ou est recouverte par une autre vue, les gestes déclenchant des rappels peuvent avoir des conséquences inattendues.
- La méthode
clearFocus()
lance une recherche de ciblage pour trouver une autre vue appropriée. En fonction de la hiérarchie des vues, cette recherche peut nécessiter des calculs complexes. Elle peut également finir par attribuer le ciblage à une vue que vous ne vous attendiez pas à voir.
Les événements de touche sont d'abord envoyés à la vue ciblée dans la hiérarchie des vues. Si cette vue ciblée ne gère pas l'événement (par exemple, si elle renvoie false
), celui-ci n'est pas envoyé à la vue parent, même s'il peut être ciblé et qu'il dispose d'un
KeyListener
. À la place, l'événement est envoyé à l'activité actuelle, qui contient la hiérarchie des vues.
Par conséquent, il peut être nécessaire d'identifier tous les événements au niveau supérieur, puis de transmettre les codes souhaités à tous les enfants.
Vous pouvez également sous-classer l'activité et remplacer la méthode
dispatchKeyEvent(KeyEvent event)
pour vous assurer que les touches sont interceptées si nécessaire ou pour les prendre en charge lorsqu'elles ne sont pas gérées dans des couches inférieures.
Le contenu et les exemples de code de cette page sont soumis aux licences décrites dans la Licence de contenu. Java et OpenJDK sont des marques ou des marques déposées d'Oracle et/ou de ses sociétés affiliées.
Dernière mise à jour le 2025/07/26 (UTC).
[[["Facile à comprendre","easyToUnderstand","thumb-up"],["J'ai pu résoudre mon problème","solvedMyProblem","thumb-up"],["Autre","otherUp","thumb-up"]],[["Il n'y a pas l'information dont j'ai besoin","missingTheInformationINeed","thumb-down"],["Trop compliqué/Trop d'étapes","tooComplicatedTooManySteps","thumb-down"],["Obsolète","outOfDate","thumb-down"],["Problème de traduction","translationIssue","thumb-down"],["Mauvais exemple/Erreur de code","samplesCodeIssue","thumb-down"],["Autre","otherDown","thumb-down"]],["Dernière mise à jour le 2025/07/26 (UTC)."],[],[],null,["# Use wrist gestures on Wear\n\nWrist gestures can enable quick, one-handed interactions with your app\nwhen a touch screen is inconvenient.\n\n\nFor example, a user can scroll\nthrough notifications with one hand while holding a cup of water with the\nother. Other use cases for wrist gestures include the following:\n\n- In a jogging app, navigating through vertical screens that show the steps taken, time elapsed, and current pace\n- In a travel app, scrolling through flight and gate information\n- In a news app, scrolling through articles\n\n\nTo review the [wrist gestures](https://support.google.com/androidwear/answer/6312406) on a watch\ndevice, confirm that gestures are\nturned on by selecting **Settings \\\u003e Advanced features \\\u003e Gestures \\\u003e Wrist Gestures\nOn** . Then complete the\nGestures tutorial on the watch by selecting **Launch Tutorial**.\n\n\n**Note:** Shaking the wrist is the system-wide back or undo gesture\nand is not available for apps to customize.\n\n\nWrist gestures can be used in the following ways, as described in this guide:\n\n- With a [curved layout](#using_wrv), which has predefined gesture actions\n- By using [key events directly](#using_key_events) to define new user actions\n\n\nEach wrist gesture is mapped to an `int` constant from the\n[KeyEvent](/reference/android/view/KeyEvent)\nclass, as shown in the following table:\n\n| Gesture | KeyEvent | Description |\n|-----------------|-------------------------------------------------------------------------------------------|------------------------------------------|\n| Flick wrist out | [`KEYCODE_NAVIGATE_NEXT`](/reference/android/view/KeyEvent#KEYCODE_NAVIGATE_NEXT) | This key code goes to the next item. |\n| Flick wrist in | [`KEYCODE_NAVIGATE_PREVIOUS`](/reference/android/view/KeyEvent#KEYCODE_NAVIGATE_PREVIOUS) | This key code goes to the previous item. |\n\nUse a curved layout to support wrist gestures\n---------------------------------------------\n\n\nThe [WearableRecyclerView](/reference/androidx/wear/widget/WearableRecyclerView) class provides a curved\nlayout for lists and automatically supports\nwrist gestures. The class has predefined actions for occurrences of\nwrist gestures when the view has focus. For information about using\nthe `WearableRecyclerView` class, see [Create lists on Wear OS](/training/wearables/ui/lists). Also, see the\n[Best practices](#best_practices) section of this guide.\n\n\n**Note:** The `WearableRecyclerView` class replaces a similar,\n[deprecated](/training/wearables/ui/wear-ui-library#deprecations) class in the Wearable Support Library.\n\n\nEven if you use a `WearableRecyclerView`, you might want to use\nconstants from the [KeyEvent](/reference/android/view/KeyEvent)\nclass. The predefined actions can be overridden by subclassing the\n`WearableRecyclerView` and re-implementing the\n`onKeyDown()` callback. The behavior can be disabled entirely\nby using [`setEnableGestureNavigation(false)`](/reference/android/support/wearable/view/WearableListView#setEnableGestureNavigation(boolean)).\nFor more information, see\n[Handle keyboard actions](/training/keyboard-input/commands).\n\nUse key events directly\n-----------------------\n\n\nYou can use key events outside of a [WearableRecyclerView](/reference/androidx/wear/widget/WearableRecyclerView) to trigger new actions in response to gesture\nevents. Importantly, these gesture events are recognized when a device is in\nactive mode, and they are delivered in the same way as all key events.\n\n\nA class that relates to user interaction, such as a `View` or an\n`Activity`, and that implements\n[KeyEvent.Callback](/reference/android/view/KeyEvent.Callback) can listen to key events that relate to\nwrist gestures just as it can listed to any other key event. The Android framework\ncalls the `View` or `Activity` that has\nfocus with the key events. For gestures, the `onKeyDown()`\nmethod callback is called when gestures occur.\n\n\nAs an example, an app can override predefined actions in a `View`\nor `Activity` that implements `KeyEvent.Callback` as follows: \n\n### Kotlin\n\n```kotlin\nclass GesturesActivity : Activity() {\n\n /* KeyEvent.Callback */\n override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {\n return when (keyCode) {\n KeyEvent.KEYCODE_NAVIGATE_NEXT -\u003e\n // Do something that advances a user View to the next item in an ordered list.\n moveToNextItem()\n KeyEvent.KEYCODE_NAVIGATE_PREVIOUS -\u003e\n // Do something that advances a user View to the previous item in an ordered list.\n moveToPreviousItem()\n else -\u003e {\n // If you did not handle it, let it be handled by the next possible element as determined\n // by the Activity.\n super.onKeyDown(keyCode, event)\n }\n }\n }\n\n /** Shows the next item in the custom list. */\n private fun moveToNextItem(): Boolean {\n ...\n // Return true if handled successfully, otherwise return false.\n return false\n }\n\n /** Shows the previous item in the custom list. */\n private fun moveToPreviousItem(): Boolean {\n ...\n // Return true if handled successfully, otherwise return false.\n return false\n }\n}\n```\n\n### Java\n\n```java\npublic final class GesturesActivity extends Activity {\n\n @Override /* KeyEvent.Callback */\n public boolean onKeyDown(int keyCode, KeyEvent event) {\n switch (keyCode) {\n case KeyEvent.KEYCODE_NAVIGATE_NEXT:\n // Do something that advances a user View to the next item in an ordered list.\n return moveToNextItem();\n case KeyEvent.KEYCODE_NAVIGATE_PREVIOUS:\n // Do something that advances a user View to the previous item in an ordered list.\n return moveToPreviousItem();\n }\n // If you did not handle it, let it be handled by the next possible element as determined by the Activity.\n return super.onKeyDown(keyCode, event);\n }\n\n /** Shows the next item in the custom list. */\n private boolean moveToNextItem() {\n boolean handled = false;\n ...\n // Return true if handled successfully, otherwise return false.\n return handled;\n }\n\n /** Shows the previous item in the custom list. */\n private boolean moveToPreviousItem() {\n boolean handled = false;\n ...\n // Return true if handled successfully, otherwise return false.\n return handled;\n }\n}\n```\n\nBest practices\n--------------\n\n- Review the [KeyEvent](/reference/android/view/KeyEvent) and [KeyEvent.Callback](/reference/android/view/KeyEvent.Callback) pages for the delivery of key events to your `View` and `Activity`.\n- Keep a consistent directional affordance: use \"flick wrist out\" for next and \"flick wrist in\" for previous.\n- Have a touch parallel for a gesture.\n- Provide visual feedback.\n- Don't use a keycode to implement functionality that would be counterintuitive to the rest of the system. For example, don't use `KEYCODE_NAVIGATE_NEXT` to cancel an action or to navigate the left-right axis with flicks.\n- Don't intercept the key events on elements that are not part of the user interface, such as views that are offscreen or partially covered. This is the same as for any key event.\n- Don't reinterpret repeated flick gestures into your own novel gesture. This might conflict with the system's \"shaking the wrist\" gesture.\n- For a view to receive gesture key events, it must have [focus](/reference/android/view/View#attr_android:focusable); see [`\n View.setFocusable()`](/reference/android/view/View#setFocusable(boolean)).\n\n Because gestures are treated as key events,\n they trigger a transition out of \"touch mode\" that might do unexpected\n things. Since users may alternate between using touch and\n gestures, the [`\n View::setFocusableInTouchmode()`](/reference/android/view/View#setFocusableInTouchMode(boolean)) method could be necessary. In some\n cases, it also could be necessary to use\n `setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS)` so\n that when focus changes after a change to or from touch mode, your\n intended view gets the focus.\n- Use [requestFocus()](/reference/android/view/View#requestFocus()) and [clearFocus()](/reference/android/view/View#clearFocus()) carefully:\n - When calling `requestFocus()`, make sure it's appropriate for the view to have focus. If the view is offscreen or is covered by another view, surprises can occur when gestures trigger callbacks.\n - The `clearFocus()` method initiates a focus search to find another suitable view. Depending on the view hierarchy, this search might require nontrivial computation. It can also end up assigning focus to a view you don't expect to receive focus.\n- Key events are delivered first to the view with focus in the view\n hierarchy. If the focused view does not handle the event---in other words, it returns\n `false`---the event is not delivered to the parent view, even\n if it can receive focus and has a [`\n KeyListener`](/reference/android/text/method/KeyListener). Rather, the event is delivered to the current activity\n holding the view hierarchy with focus.\n\n Therefore, it might be necessary to\n catch all events at the higher level, then pass relevant codes down.\n Alternatively, you might subclass the activity and override the\n [dispatchKeyEvent(KeyEvent event)](/reference/android/app/Activity#dispatchKeyEvent(android.view.KeyEvent)) method to intercept keys\n when necessary or handle them when they are not handled at\n lower layers."]]