Muchos elementos componibles tienen compatibilidad integrada con toques o clics, y también incluyen un
Lambda es onClick
. Por ejemplo, puedes crear un elemento Surface
en el que se puede hacer clic y que
incluye todo el comportamiento de Material Design apropiado para la interacción con plataformas:
Surface(onClick = { /* handle click */ }) { Text("Click me!", Modifier.padding(24.dp)) }
Sin embargo, los clics no son la única forma en que un usuario puede interactuar con esos elementos. Esta página se centra en los gestos que implican un solo puntero, donde la posición del Ese puntero no es significativo para el manejo de ese evento. Lo siguiente En la tabla, se enumeran estos tipos de gestos:
Gesto |
Descripción |
Presionar (o hacer clic) |
El puntero baja y, luego, sube. |
Presionar dos veces |
El puntero baja, sube, baja, sube |
Mantener presionado |
El puntero baja y permanece retenido por más tiempo. |
Prensa |
El puntero baja |
Responde a tocar o hacer clic
clickable
es un modificador de uso general que hace que un elemento componible reaccione a
presiones o clics. Este modificador también agrega funciones adicionales, como compatibilidad con
el enfoque, el mouse y la pluma stylus, y una indicación visual personalizable cuando
pulsado. El modificador responde a los "clics" en el sentido más amplio de la palabra, no
solo con el mouse o el dedo, sino también hacer clic en eventos a través de la entrada del teclado o cuando
usando los servicios de accesibilidad.
Imagina una cuadrícula de imágenes, en la que una imagen se muestra en pantalla completa cuando un usuario hace clic en él:
Puedes agregar el modificador clickable
a cada elemento de la cuadrícula para implementar esto.
comportamiento:
@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 } ) } }
El modificador clickable
también agrega un comportamiento adicional:
interactionSource
yindication
, que dibujan un ripple de forma predeterminada cuando se el usuario presiona el elemento componible. Para obtener más información sobre cómo personalizar estas opciones, consulte la página Administración de usuarios interacciones.- Permite que los servicios de accesibilidad interactúen con el elemento estableciendo la información semántica.
- Admite la interacción con teclado o joystick, ya que permite enfocar y presionar
Enter
o el centro del pad direccional para interactuar - Hacer que el elemento se pueda colocar sobre el elemento para que responda cuando se coloca el cursor sobre el mouse o la pluma stylus por encima.
Mantén presionado para mostrar un menú contextual contextual
combinedClickable
te permite agregar un comportamiento de presionar dos veces o mantener presionado en
además del comportamiento normal de clics. Puedes usar combinedClickable
para mostrar un
Menú contextual cuando un usuario toca y mantiene presionada una imagen de cuadrícula:
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 } ) }
Como práctica recomendada, debes incluir respuesta táctil cuando el usuario
mantiene presionados los elementos, por lo que el fragmento incluye los
performHapticFeedback
.
Presiona una lámina para descartar un elemento componible
En los ejemplos anteriores, clickable
y combinedClickable
agregan información útil
a tus elementos componibles. Muestran una indicación visual sobre la interacción,
responden a la acción de colocar el cursor sobre ellos e incluyen compatibilidad con enfoque, teclado y accesibilidad. Sin embargo,
este comportamiento adicional no siempre es conveniente.
Veamos la pantalla de detalles de la imagen. El fondo debe ser semitransparente. y el usuario debería poder presionar ese fondo para descartar la pantalla de detalles:
En este caso, ese fondo no debe tener ninguna indicación visual en
interactiva, no debe responder a la acción de colocar el cursor sobre un elemento, no debe ser enfocable y su
la respuesta a los eventos de accesibilidad y de teclado difiere de la de una
componible. En lugar de tratar de adaptar el comportamiento de clickable
, puedes descartar
hasta un nivel de abstracción más bajo y usar directamente el modificador pointerInput
en combinación con el método 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)) ) }
Como tecla del modificador pointerInput
, pasas la lambda onClose
. Esta
vuelve a ejecutar automáticamente la expresión lambda y se asegura de que se llame a la devolución de llamada correcta.
cuando el usuario presiona la lámina.
Presiona dos veces para acercar
A veces, clickable
y combinedClickable
no incluyen suficiente información
responder a la interacción de la manera correcta. Por ejemplo, los elementos componibles podrían
necesitan acceso a la posición dentro de los límites del elemento componible donde la interacción
tuvo lugar.
Veamos la pantalla de detalles de la imagen de nuevo. Una práctica recomendada es posible acercar la imagen tocando dos veces:
Como puedes ver en el video, el acercamiento se produce alrededor de la posición en la que se presionaba
para cada evento. El resultado es diferente cuando acercamos la parte izquierda de la imagen.
en comparación con la parte derecha. Podemos usar el modificador pointerInput
en combinación
con detectTapGestures
para incorporar la posición del toque en nuestra
cálculo:
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 } )
Recomendaciones para ti
- Nota: El texto del vínculo se muestra cuando JavaScript está desactivado
- Información sobre los gestos
- Material Design 2 en Compose
- Kotlin para Jetpack Compose