Viele Composables bieten integrierte Unterstützung für Berührungen oder Klicks und enthalten ein onClick-Lambda. Sie können beispielsweise ein anklickbares Surface erstellen, das alle Material Design-Verhaltensweisen enthält, die für die Interaktion mit Oberflächen geeignet sind:
Surface(onClick = { /* handle click */ }) { Text("Click me!", Modifier.padding(24.dp)) }
Klicks sind jedoch nicht die einzige Möglichkeit, wie Nutzer mit Composables interagieren können. Auf dieser Seite geht es um Gesten, die einen einzelnen Zeiger umfassen, wobei die Position dieses Zeigers für die Verarbeitung dieses Ereignisses nicht relevant ist. In der folgenden Tabelle sind diese Arten von Touch-Gesten aufgeführt:
Touch-Geste |
Beschreibung |
Tippen (oder klicken) Sie auf |
Mauszeiger bewegt sich nach unten und dann nach oben |
Doppeltippen |
Der Zeiger bewegt sich nach unten, oben, unten, oben. |
Lange drücken |
Der Zeiger wird nach unten bewegt und länger gehalten. |
Presse |
Zeiger bewegt sich nach unten |
Auf Tippen oder Klicken reagieren
clickable ist ein häufig verwendeter Modifikator, mit dem ein Compose-Element auf Tippen oder Klicken reagiert. Dieser Modifikator bietet auch zusätzliche Funktionen, z. B. Unterstützung für Fokus, Maus- und Eingabestift-Hover sowie eine anpassbare visuelle Anzeige beim Drücken. Der Modifikator reagiert auf „Klicks“ im weitesten Sinne des Wortes – nicht nur mit der Maus oder dem Finger, sondern auch auf Klick-Events über die Tastatur oder bei Verwendung von Bedienungshilfen.
Stellen Sie sich ein Raster von 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 ein zusätzliches Verhalten hinzu:
interactionSourceundindication, die standardmäßig einen Welleneffekt zeichnen, wenn ein Nutzer auf die komponierbare Funktion tippt. Informationen zum Anpassen dieser Einstellungen finden Sie auf der Seite Umgang mit Nutzerinteraktionen.- Ermöglicht Bedienungshilfen, mit dem Element zu interagieren, indem die Semantikinformationen festgelegt werden.
- Unterstützt die Interaktion über Tastatur oder Joystick, indem der Fokus gesetzt und
Enteroder die Mitte des Steuerkreuzes gedrückt wird. - Machen Sie das Element hoverbar, damit es auf das Bewegen der Maus oder des Eingabestifts darüber reagiert.
Lange drücken, um ein Kontextmenü einzublenden
Mit combinedClickable können Sie zusätzlich zum normalen Klickverhalten ein Verhalten für Doppeltippen oder langes Drücken hinzufügen. Mit combinedClickable können Sie ein Kontextmenü einblenden, wenn ein Nutzer ein Bild im Raster berührt und 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 } ) }
Es empfiehlt sich, haptisches Feedback zu geben, wenn der Nutzer lange auf Elemente drückt. Deshalb enthält das Snippet den Aufruf performHapticFeedback.
Composable durch Tippen auf eine Scrim schließen
In den obigen Beispielen fügen clickable und combinedClickable Ihren Composables nützliche Funktionen hinzu. Sie zeigen bei Interaktion eine visuelle Anzeige, reagieren auf Hover und bieten Unterstützung für Fokus, Tastatur und Bedienungshilfen. Dieses zusätzliche Verhalten ist jedoch nicht immer wünschenswert.
Sehen wir uns die Detailansicht des Bildes an. Der Hintergrund sollte halbtransparent sein und der Nutzer sollte auf den Hintergrund tippen können, um die Detailansicht zu schließen:
In diesem Fall sollte der Hintergrund bei Interaktionen keine visuelle Anzeige haben, nicht auf Hover reagieren, nicht fokussierbar sein und seine Reaktion auf Tastatur- und Bedienungshilfenereignisse sollte sich von der eines typischen Composables unterscheiden. Anstatt zu versuchen, das Verhalten von clickable anzupassen, können Sie eine niedrigere Abstraktionsebene verwenden 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 des pointerInput-Modifikators übergeben Sie das onClose-Lambda. Dadurch wird die Lambda-Funktion automatisch noch einmal ausgeführt, sodass der richtige Callback aufgerufen wird, wenn der Nutzer auf die Scrim tippt.
Zum Zoomen doppeltippen
Manchmal enthalten clickable und combinedClickable nicht genügend Informationen, um angemessen auf die Interaktion 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. Eine Best Practice ist es, das Heranzoomen des Bildes durch Doppeltippen zu ermöglichen:
Wie im Video zu sehen ist, wird um die Position des Tippereignisses herum herangezoomt. Das Ergebnis ist unterschiedlich, je nachdem, ob wir den linken oder den rechten Teil des Bildes heranzoomen. Wir können den Modifikator pointerInput in Kombination mit 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 Sie
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Gesten
- Material Design 2 in Compose
- Kotlin für Jetpack Compose