Sur Wear OS 7 (niveau d'API 37) et versions ultérieures, un framework de gestes à une main, ainsi qu'une API faisant partie de Compose for Wear OS, permettent aux utilisateurs d'interagir avec votre application sans la toucher.
Bien qu'il soit initialement compatible avec les appareils Pixel Watch (Pixel Watch 3 et modèles ultérieurs), le framework est disponible pour tous les OEM. En adoptant cette API, la prise en charge des gestes de votre application s'adapte automatiquement à l'ensemble de l'écosystème à mesure que la prise en charge matérielle s'étend.
Pour aider les utilisateurs à découvrir les gestes disponibles sans encombrer l'UI, le framework Wear OS fournit des indicateurs de gestes animés. Ces repères visuels indiquent où un geste peut être effectué, tandis que le système gère automatiquement la cadence d'affichage et la fréquence de désactivation en fonction des préférences de l'utilisateur.
Gestes et actions compatibles
Le framework de gestes Wear OS est compatible avec deux types de gestes :
- Action principale (pincer deux fois) : correspond à l'action principale sur un écran, comme répondre à un appel ou activer/désactiver la lecture de contenus multimédias.
- Action de fermeture (rotation du poignet) : correspond à la navigation vers l'arrière, à la fermeture d'une boîte de dialogue ou à l'annulation d'une invite.
Configurer les gestes dans Compose
Bien que l'API de gestes à une main puisse améliorer votre UI, il est important de garder à l'esprit que certains matériels et OEM ne sont pas compatibles avec ces gestes. Si l'API détecte que votre application s'exécute sur l'un de ces appareils non compatibles, la bibliothèque effectue automatiquement une opération sans effet, sans affecter les interactions tactiles standards.
Comme pour les comportements Compose standards, vous activez les gestes à une main sur les éléments d'UI à l'aide de modificateurs. Vous configurez les gestes de votre application en fonction de l'action à effectuer (principale ou fermeture) et d'un gestureId pour coordonner les préférences utilisateur au niveau du système, telles que la cadence d'affichage des conseils et la désactivation de la fréquence. Vous exprimez cette configuration en créant un objet OneHandedGestureConfiguration. Nous vous recommandons d'utiliser la fonction rememberOneHandedGestureConfiguration pour le créer. C'est également dans OneHandedGestureConfiguration que vous pouvez définir la priorité du geste.
La fonction rememberOneHandedGestureConfiguration suit l'historique des interactions de l'utilisateur entre les recompositions sans exposer l'état de l'application. Une fois que votre application a créé la configuration, elle doit la transmettre à Modifier.oneHandedGesture sur votre composable interactif.
Pour aider les utilisateurs à découvrir les gestes disponibles, la bibliothèque fournit la méthode OneHandedGestureClickIndicator. Cette méthode sert de wrapper et remplace son contenu sous-jacent pour indiquer à l'utilisateur qu'une action gestuelle est disponible.
Composants interactifs
Pour activer les gestes sur un élément interactif tel qu'un bouton, créez une configuration spécifiant OneHandedGestureAction.Primary et appliquez le modificateur oneHandedGesture. Transmettez le même MutableInteractionSource à la fois au contrôle et au modificateur afin que les événements de geste émettent un retour visuel de pression sur le contrôle.
Pour activer l'indicateur de geste, créez et mémorisez une instance de OneHandedGestureClickIndicatorState. Ensuite, pour déclencher le retour visuel, appelez showIndicator dans le rappel onGestureAvailable fourni par le modificateur oneHandedGesture, qui indique au système qu'un événement d'indication s'est produit. Une fois appelé, le composant remplace brièvement son contenu normal par une animation de geste.
var isPlaying by remember { mutableStateOf(false) } val onClick = { isPlaying = !isPlaying } val gestureConfig = rememberOneHandedGestureConfiguration( action = OneHandedGestureAction.Primary ) val indicatorState = remember { OneHandedGestureClickIndicatorState() } val coroutineScope = rememberCoroutineScope() val interactionSource = remember { MutableInteractionSource() } Button( onClick = onClick, interactionSource = interactionSource, modifier = Modifier .fillMaxWidth() .oneHandedGesture( gestureConfiguration = gestureConfig, interactionSource = interactionSource, onGestureLabel = if (isPlaying) "pause" else "play", onGestureAvailable = { coroutineScope.launch { indicatorState.showIndicator() } }, onGesture = onClick ) ) { OneHandedGestureClickIndicator( gestureConfiguration = gestureConfig, state = indicatorState ) { Text(if (isPlaying) "Pause" else "Play", modifier = Modifier.fillMaxWidth()) } }
Conteneurs déroulants
Pour les écrans ou les listes déroulants, créez une configuration spécifiant OneHandedGestureAction.Primary et appliquez le modificateur oneHandedGesture à votre conteneur, en appelant un utilitaire de défilement tel que scrollDown.
Pour fournir un retour visuel pour les actions de défilement, vous pouvez utiliser OneHandedGestureScrollIndicator. Ce composant fonctionne comme un indicateur de défilement standard qui affiche la position de défilement, mais il peut également indiquer qu'un geste de défilement est disponible pour l'utilisateur. Cet indicateur est généralement transmis à l'emplacement scrollIndicator d'un ScreenScaffold et est associé à l'état d'un conteneur à défilement, tel qu'un TransformingLazyColumn. Il observe également un OneHandedGestureScrollIndicatorState pour gérer ses transitions visuelles.
Pour déclencher le retour visuel, appelez showIndicator sur cet état, généralement dans le rappel onGestureAvailable du modificateur oneHandedGesture.
Une fois déclenché, l'indicateur remplace temporairement son état visuel standard par une séquence d'animation de geste pour alerter l'utilisateur.
val scrollState = rememberTransformingLazyColumnState() val gestureConfig = rememberOneHandedGestureConfiguration( action = OneHandedGestureAction.Primary, priority = OneHandedGesturePriority.Scrollable ) val indicatorState = remember(gestureConfig) { OneHandedGestureScrollIndicatorState() } val coroutineScope = rememberCoroutineScope() ScreenScaffold( scrollState = scrollState, scrollIndicator = { OneHandedGestureScrollIndicator( gestureConfiguration = gestureConfig, indicatorState = indicatorState, scrollState = scrollState, modifier = Modifier.align(Alignment.CenterEnd) ) } ) { contentPadding -> TransformingLazyColumn( state = scrollState, contentPadding = contentPadding, modifier = Modifier .fillMaxSize() .oneHandedGesture( gestureConfiguration = gestureConfig, onGestureLabel = "scroll", onGestureAvailable = { coroutineScope.launch { indicatorState.showIndicator() } }, onGesture = { OneHandedGestureDefaults.scrollDown(scrollState) } ) ) { items(10) { index -> Text("Item $index", modifier = Modifier.padding(8.dp)) } } }
Combiner plusieurs gestes
Vous pouvez configurer un geste de défilement et un geste de clic avec la même action principale en ajoutant gesturePriority à votre objet OneHandedGestureConfiguration :
OneHandedGesturePriority.Clickable(le plus élevé) : Attribuez-le aux commandes interactives, telles que celles de typeButtonouCard, afin qu'elles capturent les gestes lorsqu'elles sont visibles à l'écran.OneHandedGesturePriority.Scrollable(moyen) : attribuez-le aux conteneurs à défilement ou paginables afin qu'ils cèdent la place aux enfants cliquables, mais qu'ils défilent lorsqu'aucun contrôle cliquable n'est visible.OneHandedGesturePriority.Unspecified(la plus basse) : priorité non attribuée. Il s'agit de la valeur par défaut pour un geste dont lepriorityn'est pas défini.
En définissant explicitement priority = OneHandedGesturePriority.Clickable sur un bouton interne et priority = OneHandedGesturePriority.Scrollable sur sa liste parente, le système peut afficher ce comportement de priorité des gestes.
Lorsque l'utilisateur déclenche l'action principale par le biais du geste à une main, la liste défile d'abord vers le bas jusqu'à ce que le bouton soit visible, puis l'action de clic sur le bouton est capturée.
Tester et déboguer les gestes avec ADB
Vous pouvez tester les gestes à une main sur un appareil physique ou un émulateur sans effectuer de mouvements physiques du poignet en utilisant Android Debug Bridge (adb) et le service système IWearGestureService.
Activer la simulation de gestes
Avant de simuler des gestes à l'aide d'ADB, configurez les paramètres de votre appareil et les remplacements de contraintes :
Vérifiez que votre appareil Wear OS est équipé de Wear OS 7 (niveau d'API 37) ou version ultérieure :
adb shell getprop ro.build.version.sdkSi vous effectuez des tests sur un appareil physique qui n'est pas à votre poignet ou qui est en charge, remplacez la contrainte hors corps afin que le framework de gestes reste actif :
adb shell cmd IWearGestureService override-constraints offbody-state
Déclencher des événements de geste à l'aide d'ADB
Pour simuler le geste Pincer deux fois (qui correspond à l'action Primary sur les montres Pixel), exécutez la commande ADB shell suivante :
adb shell cmd IWearGestureService gesture DoublePinch
Pour simuler le geste Tourner le poignet (qui correspond à l'action Dismiss sur les montres Pixel), exécutez la commande ADB shell suivante :
adb shell cmd IWearGestureService gesture WristTurn
Réinitialiser le suivi des suggestions de gestes
Le système suit l'historique des interactions de l'utilisateur et affiche des suggestions de gestes flottantes en fonction du paramètre de cadence globale (par exemple, Toujours ou Tous les jours). Lorsque vous déboguez les indicateurs de geste de votre application, réinitialisez cet historique de suivi afin que les indices réapparaissent pour votre package :
Sur les builds ou les émulateurs
userdebug:adb shell cmd IWearGestureService hint clear <your_package_name>Sur les versions commerciales (
user) :Sur les appareils commerciaux sans accès root,
hint clearest bloqué par les autorisations système. Effacez les données locales de l'application pour réinitialiser la découverte des indices :adb shell pm clear <your_package_name>
Restaurer les contraintes par défaut
Pour réinitialiser tous les forçages de contraintes de débogage une fois les tests terminés :
adb shell cmd IWearGestureService override-constraints reset
Résoudre les problèmes d'injection de gestes
Si votre application ne reçoit pas les gestes simulés :
Vérifiez que l'écran de la montre est allumé et n'est pas en veille. Le framework de gestes ne distribue pas les gestes aux applications lorsque l'écran est éteint ou en mode ambiant. Pour réactiver l'écran à l'aide d'ADB, exécutez la commande suivante :
adb shell input keyevent KEYCODE_WAKEUPVérifiez si votre application est enregistrée en tant qu'abonné aux gestes actif et si elle détient actuellement le focus de la fenêtre :
adb shell cmd IWearGestureService get-active-gestures -readableLorsque l'écran de gestes de votre application est au premier plan et que l'écran est activé, cette commande renvoie
[DoublePinch]ou[DoublePinch, WristTurn]. Si une liste vide ([]) est renvoyée, vérifiez si votre fenêtre est sélectionnée ou si des contraintes hors corps bloquent l'activation.Inspectez l'état du service de gestes internes et les jetons d'abonnés actifs :
adb shell dumpsys IWearGestureService
Ressources supplémentaires
Pour obtenir des conseils de conception sur quand et où utiliser les gestes à une main, consultez Gestes à une main.
Recommandations personnalisées
- Remarque : Le texte du lien s'affiche lorsque JavaScript est désactivé
- Guide de conception des gestes à une main