Tippen und drücken

Viele zusammensetzbare Funktionen unterstützen das Tippen oder Klicken und enthalten ein onClick Lambda. Sie können beispielsweise eine anklickbare Surface erstellen, die umfasst alle Material Design-Verhaltensweisen, 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 Nutzende mit zusammensetzbaren Funktionen interagieren können. Diese Seite konzentriert sich auf Gesten, die einen einzelnen Zeiger umfassen, dass dieser Zeiger für die Verarbeitung dieses Ereignisses nicht von Bedeutung ist. Die folgenden sind folgende Arten von Gesten aufgeführt:

Touch-Geste

Beschreibung

Tippen (oder klicken)

Zeiger nach unten und dann nach oben

Doppeltippen

Zeiger geht nach unten, nach oben, nach unten, nach oben

Lange drücken

Zeiger fällt nach unten und wird länger gehalten

Presse

Zeiger fällt nach unten

Auf Antippen oder Klicken reagieren

clickable ist ein häufig verwendeter Modifikator, mit dem eine zusammensetzbare Funktion auf Tippen oder Klicken. Dieser Modifikator bietet zusätzliche Funktionen, wie z. B. Unterstützung für Fokus, Maus und Eingabestift bewegt, sowie eine anpassbare visuelle Anzeige, wenn gedrückt. Der Modifikator reagiert auf „Klicks“ im weitesten Sinne des Wortes – nur mit Maus oder Finger, sondern auch per Tastatureingabe oder bei Bedienungshilfen nutzen.

Stellen Sie sich ein Bildraster vor, bei dem ein Bild im Vollbildmodus angezeigt wird, darauf klickt:

Sie können jedem Element im Raster den clickable-Modifikator hinzufügen, um dies zu implementieren Verhalten:

@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 clickable-Modifikator bietet außerdem zusätzliche Funktionen:

  • interactionSource und indication, die standardmäßig eine Welle zeichnen, wenn ein Nutzende auf die zusammensetzbare Funktion. Informationen zum Anpassen finden Sie unter Handhabung von Interaktionen angezeigt.
  • Erlaubt Bedienungshilfen, mit dem Element zu interagieren, indem die Semantik.
  • Unterstützt die Interaktion über Tastatur oder Joystick, indem Fokus und Drücken der Anzeige möglich sind Enter oder die Mitte des Steuerkreuzes, um zu interagieren.
  • Element schwebbar machen, damit es auf das Bewegen der Maus oder des Eingabestifts reagiert darüber sprechen.

Lange drücken, um Kontextmenü einzublenden

Über combinedClickable können Sie Funktionen für Doppeltippen oder langes Drücken in neben dem normalen Klickverhalten. Mit combinedClickable können Sie Folgendes anzeigen: Kontextmenü, wenn ein Nutzer ein Rasterbild 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 }
    )
}

Als Best Practice sollten Sie haptisches Feedback einbeziehen, Elemente lange drücken. Deshalb enthält das Snippet Aufruf von performHapticFeedback.

Zusammensetzbare Funktion durch Antippen eines Scrums schließen

In den Beispielen oben fügen clickable und combinedClickable nützliche Funktionalität hinzufügen. Sie liefern visuelle Hinweise auf die Interaktion, auf das Bewegen des Mauszeigers reagieren und Unterstützung für Fokus, Tastatur und Bedienungshilfen bieten. Aber ist dieses zusätzliche Verhalten nicht immer erwünscht.

Sehen wir uns den Bildschirm mit den Bilddetails an. Der Hintergrund sollte halbtransparent sein. Der Nutzer sollte in der Lage sein, auf diesen Hintergrund zu tippen, um den Detailbildschirm zu schließen:

In diesem Fall sollte der Hintergrund keinen visuellen Hinweis auf die sollte nicht auf den Mauszeiger reagiert werden, nicht fokussierbar sein die Reaktion auf Tastatur- und Eingabehilfenereignisse, zusammensetzbar. Anstatt zu versuchen, das Verhalten von clickable anzupassen, können Sie auf eine niedrigere Abstraktionsebene herunter und verwenden Sie direkt den pointerInput-Modifikator in Kombination mit der detectTapGestures-Methode:

@OptIn(ExperimentalComposeUiApi::class)
@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-Modifikator übergeben Sie das Lambda onClose. Dieses führt die Lambda-Funktion automatisch noch einmal aus und sorgt dafür, dass der richtige Callback aufgerufen wird. wenn Nutzende auf das Gitter tippen.

Zum Zoomen doppeltippen

Manchmal enthalten clickable und combinedClickable nicht genügend Informationen um richtig auf die Interaktion zu reagieren. Zusammensetzbare Funktionen Zugriff auf die Position innerhalb der Grenzen der zusammensetzbaren Funktion benötigen, an der die Interaktion stattfand.

Sehen wir uns noch einmal den Bildschirm mit den Bilddetails an. Es empfiehlt sich, kann das Bild durch Doppeltippen vergrößert werden:

Wie im Video zu sehen ist, wird um die Position des Tippens herum herangezoomt . Das Ergebnis ist anders, wenn wir den linken Teil des Bildes heranzoomen. und zum richtigen Teil. Wir können den pointerInput-Modifikator in einer Kombination detectTapGestures, um die Tippposition in unser Berechnung:

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
        }
)