Viele Composeables bieten integrierte Unterstützung für Tippen oder Klicken und enthalten eine onClick
-Lambda-Funktion. Sie können beispielsweise ein anklickbares Surface
erstellen, das alle für die Interaktion mit Oberflächen erforderlichen Material Design-Verhaltensweisen enthält:
Surface(onClick = { /* handle click */ }) { Text("Click me!", Modifier.padding(24.dp)) }
Klicks sind jedoch nicht die einzige Möglichkeit, wie Nutzer mit Composeables interagieren können. Auf dieser Seite geht es hauptsächlich um Touch-Gesten, bei denen nur ein Zeiger verwendet wird und dessen Position für die Verarbeitung des Ereignisses nicht von Bedeutung ist. In der folgenden Tabelle sind diese Touch-Gesten aufgeführt:
Touch-Geste |
Beschreibung |
Tippen (oder klicken) |
Der Cursor bewegt sich nach unten und dann nach oben. |
Doppeltippen |
Der Cursor bewegt sich nach unten, oben, unten und oben. |
Lange drücken |
Der Cursor bewegt sich nach unten und wird länger gehalten |
Presse |
Der Cursor bewegt sich nach unten. |
Auf Antippen oder Klicken reagieren
clickable
ist ein häufig verwendeter Modifikator, mit dem ein Composeable auf Tippen oder Klicks reagiert. Dieser Modifikator bietet auch zusätzliche Funktionen wie Unterstützung für den Fokus, das Bewegen der Maus und des Eingabestifts sowie eine anpassbare visuelle Anzeige, wenn er gedrückt wird. Der Modifikator reagiert auf „Klicks“ im weitesten Sinne des Wortes – nicht nur mit der Maus oder dem Finger, sondern auch auf Klickereignisse über die Tastatureingabe oder bei Verwendung von Bedienungshilfen.
Stellen Sie sich ein Raster mit Bildern vor, bei dem ein Bild im Vollbildmodus angezeigt wird, wenn ein Nutzer darauf klickt:
Sie können jedem Element im Raster den Modifikator clickable
hinzufügen, um dieses Verhalten zu implementieren:
@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 } ) } }
Der Modifikator clickable
fügt außerdem zusätzliches Verhalten hinzu:
interactionSource
undindication
, die standardmäßig eine Welle zeichnen, wenn ein Nutzer auf das Kompositionenelement tippt. Weitere Informationen zum Anpassen finden Sie auf der Seite Nutzerinteraktionen verarbeiten.- Ermöglicht es Diensten für Barrierefreiheit, mit dem Element zu interagieren, indem die semantischen Informationen festgelegt werden.
- Unterstützt die Interaktion über Tastatur oder Joystick, indem der Fokus gesetzt und auf
Enter
oder die Mitte des Steuerkreuzes gedrückt wird. - Achten Sie darauf, dass das Element anwählbar ist, damit es reagiert, wenn die Maus oder der Eingabestift darüber bewegt wird.
Langes Drücken, um ein Kontextmenü aufzurufen
Mit combinedClickable
können Sie zusätzlich zum normalen Klickverhalten ein Doppeltippen oder langes Drücken hinzufügen. Mit combinedClickable
können Sie ein Kontextmenü anzeigen lassen, wenn ein Nutzer ein Rasterbild antippt und gedrückt hält:
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 } ) }
Als Best Practice sollten Sie haptisches Feedback einbinden, wenn der Nutzer Elemente lange drückt. Aus diesem Grund enthält das Snippet die performHapticFeedback
-Aufrufmethode.
Ein Composeable durch Tippen auf einen Scrim schließen
In den obigen Beispielen fügen clickable
und combinedClickable
Ihren Composeables nützliche Funktionen hinzu. Sie zeigen eine visuelle Interaktionsanzeige, reagieren auf Mouseover-Ereignisse und unterstützen Fokus, Tastatur und Barrierefreiheit. Dieses zusätzliche Verhalten ist jedoch nicht immer wünschenswert.
Sehen wir uns den Bildschirm mit den Bilddetails an. Der Hintergrund sollte halbtransparent sein und der Nutzer sollte auf diesen Hintergrund tippen können, um den Detailbildschirm zu schließen:
In diesem Fall sollte dieser Hintergrund keine visuellen Interaktionshinweise haben, nicht auf das Bewegen des Mauszeigers reagieren, nicht fokussierbar sein und seine Reaktion auf Tastatur- und Barrierefreiheitsereignisse sollte sich von der eines typischen Composeables unterscheiden. Anstatt das Verhalten von clickable
anzupassen, können Sie zu einer niedrigeren Abstraktionsebene wechseln und den Modifikator pointerInput
direkt in Kombination mit der Methode detectTapGestures
verwenden:
@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)) ) }
Als Schlüssel für den pointerInput
-Modifikator übergeben Sie das onClose
-Lambda. Dadurch wird das Lambda automatisch noch einmal ausgeführt, damit der richtige Rückruf aufgerufen wird, wenn der Nutzer auf den scrim tippt.
Zum Zoomen doppeltippen
Manchmal enthalten clickable
und combinedClickable
nicht genügend Informationen, um auf die Interaktion richtig zu reagieren. Beispielsweise benötigen Composables möglicherweise Zugriff auf die Position innerhalb der Grenzen des Composables, an der die Interaktion stattgefunden hat.
Sehen wir uns noch einmal den Bildschirm mit den Bilddetails an. Es empfiehlt sich, das Bild durch Doppeltippen heranzuzoomen:
Wie Sie im Video sehen, wird herangezoomt, wenn Sie auf die Karte tippen. Das Ergebnis ist unterschiedlich, wenn wir auf den linken oder rechten Teil des Bildes heranzoomen. Wir können den pointerInput
-Modifikator in Kombination mit dem detectTapGestures
verwenden, um die Tippposition in unsere Berechnung einzubeziehen:
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 } )
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Gesten
- Material Design 2 in der compose-Ansicht
- Kotlin für Jetpack Compose