De nombreux composables sont compatibles avec les appuis ou les clics, et incluent un
Lambda onClick
. Par exemple, vous pouvez créer un élément Surface
cliquable qui
inclut tous les comportements Material Design adaptés à l'interaction avec les surfaces:
Surface(onClick = { /* handle click */ }) { Text("Click me!", Modifier.padding(24.dp)) }
Mais les clics ne sont pas le seul moyen pour un utilisateur d'interagir avec les composables. Cette page se concentre sur les gestes impliquant un seul pointeur, où la position d'un ce pointeur n'est pas important pour le traitement de cet événement. Les éléments suivants : répertorie les types de gestes suivants:
Geste |
Description |
Appuyer (ou cliquer) |
Le pointeur descend, puis vers le haut |
Appuyez deux fois |
Le pointeur descend, haut, bas, haut |
Appuyer de manière prolongée |
Le pointeur descend et est maintenu plus longtemps enfoncé |
Presse |
Le pointeur baisse |
Répondre aux gestes d'appui ou de clic
clickable
est un modificateur couramment utilisé qui permet à un composable de réagir à
tapotements ou clics. Ce modificateur ajoute également des fonctionnalités supplémentaires, comme la prise en charge de
le focus, le survol avec la souris et le stylet, et une indication visuelle personnalisable
est maintenue enfoncée. Le modificateur répond aux "clics" au sens le plus large du terme,
uniquement avec la souris ou le doigt, mais aussi pour les événements de clic via la saisie au clavier ou lorsque
à l'aide de services d'accessibilité.
Imaginez une grille d'images, où une image s'affiche en plein écran lorsqu'un utilisateur clique dessus:
Vous pouvez ajouter le modificateur clickable
à chaque élément de la grille pour implémenter cela.
comportement:
@Composable private fun ImageGrid(photos: List<Photo>) { var activePhotoId by rememberSaveable { mutableStateOf<Int?>(null) } LazyVerticalGrid(columns = GridCells.Adaptive(minSize = 128.dp)) { items(photos, { it.id }) { photo -> ImageItem( photo, Modifier.clickable { activePhotoId = photo.id } ) } } if (activePhotoId != null) { FullScreenImage( photo = photos.first { it.id == activePhotoId }, onDismiss = { activePhotoId = null } ) } }
Le modificateur clickable
ajoute également un comportement supplémentaire:
interactionSource
etindication
, qui dessinent une ondulation par défaut lorsqu'un appuie sur le composable. Découvrez comment les personnaliser dans la section Gérer les utilisateurs interactions.- Permet aux services d'accessibilité d'interagir avec l'élément en définissant des informations sémantiques.
- Prise en charge des interactions avec le clavier ou le joystick en permettant la mise au point et en appuyant sur
Enter
ou le centre du pavé directionnel pour interagir. - Faites en sorte que l'élément puisse être survolé, afin qu'il réagisse au survol de la souris ou du stylet. dessus.
Appuyer de manière prolongée pour afficher un menu contextuel contextuel
combinedClickable
vous permet d'ajouter le comportement de double appui ou d'appui de manière prolongée dans
en plus des clics normaux. Vous pouvez utiliser combinedClickable
pour afficher
Menu contextuel lorsqu'un utilisateur touche de manière prolongée une image de grille:
var contextMenuPhotoId by rememberSaveable { mutableStateOf<Int?>(null) } val haptics = LocalHapticFeedback.current LazyVerticalGrid(columns = GridCells.Adaptive(minSize = 128.dp)) { items(photos, { it.id }) { photo -> ImageItem( photo, Modifier .combinedClickable( onClick = { activePhotoId = photo.id }, onLongClick = { haptics.performHapticFeedback(HapticFeedbackType.LongPress) contextMenuPhotoId = photo.id }, onLongClickLabel = stringResource(R.string.open_context_menu) ) ) } } if (contextMenuPhotoId != null) { PhotoActionsSheet( photo = photos.first { it.id == contextMenuPhotoId }, onDismissSheet = { contextMenuPhotoId = null } ) }
Nous vous recommandons d'inclure
un retour haptique lorsque l'utilisateur
appuie de manière prolongée sur les éléments. C'est pourquoi l'extrait inclut le
Appel de performHapticFeedback
.
Fermer un composable en appuyant sur un fond
Dans les exemples ci-dessus, clickable
et combinedClickable
ajoutent des éléments
à vos composables. Ils montrent une indication visuelle
de l'interaction,
répondre aux survols et inclure le focus, le clavier et une prise en charge de l'accessibilité. Toutefois,
ce comportement supplémentaire n'est pas toujours souhaitable.
Examinons l'écran des détails de l'image. L'arrière-plan doit être semi-transparent L'utilisateur doit pouvoir appuyer sur cet arrière-plan pour fermer l'écran d'informations:
Dans ce cas, cet arrière-plan ne
doit avoir aucune indication visuelle sur
ne doit pas répondre au passage de la souris, ne doit pas être sélectionnable, et son
de réponse aux événements de clavier et d'accessibilité diffère de celle d'un
composable. Au lieu d'essayer d'adapter le comportement de clickable
, vous pouvez supprimer
jusqu'à un niveau d'abstraction inférieur et utiliser directement le modificateur pointerInput
en combinaison avec la méthode detectTapGestures
:
@Composable private fun Scrim(onClose: () -> Unit, modifier: Modifier = Modifier) { val strClose = stringResource(R.string.close) Box( modifier // handle pointer input .pointerInput(onClose) { detectTapGestures { onClose() } } // handle accessibility services .semantics(mergeDescendants = true) { contentDescription = strClose onClick { onClose() true } } // handle physical keyboard input .onKeyEvent { if (it.key == Key.Escape) { onClose() true } else { false } } // draw scrim .background(Color.DarkGray.copy(alpha = 0.75f)) ) }
En tant que clé du modificateur pointerInput
, vous transmettez le lambda onClose
. Ce
réexécute automatiquement le lambda, en s'assurant que le rappel approprié est appelé
lorsque l'utilisateur
appuie sur le fond.
Appuyer deux fois pour zoomer
Parfois, clickable
et combinedClickable
n'incluent pas suffisamment d'informations
de répondre à l’interaction
de la bonne manière. Par exemple, les composables peuvent
besoin d'accéder à la position dans les limites du composable où l'interaction
s'est déroulée.
Regardons à nouveau l'écran des détails de l'image. Une bonne pratique consiste à rendre possibilité de faire un zoom avant sur l'image en appuyant deux fois:
Comme vous pouvez le voir dans la vidéo, un zoom avant se produit autour de l'endroit où
. Le résultat est différent lorsque l'on fait un zoom avant sur la partie gauche de l'image
par rapport à la bonne partie. Nous pouvons utiliser le modificateur pointerInput
en combinaison
avec detectTapGestures
pour intégrer la position de l'appui dans notre
calcul:
var zoomed by remember { mutableStateOf(false) } var zoomOffset by remember { mutableStateOf(Offset.Zero) } Image( painter = rememberAsyncImagePainter(model = photo.highResUrl), contentDescription = null, modifier = modifier .pointerInput(Unit) { detectTapGestures( onDoubleTap = { tapOffset -> zoomOffset = if (zoomed) Offset.Zero else calculateOffset(tapOffset, size) zoomed = !zoomed } ) } .graphicsLayer { scaleX = if (zoomed) 2f else 1f scaleY = if (zoomed) 2f else 1f translationX = zoomOffset.x translationY = zoomOffset.y } )
Recommandations personnalisées
- Remarque : Le texte du lien s'affiche lorsque JavaScript est désactivé
- Comprendre les gestes
- Material Design 2 dans Compose
- Kotlin pour Jetpack Compose