Ziehen, wischen und schleppen

Der draggable-Modifikator ist der übergeordnete Einstiegspunkt für Gesten in einer einzelnen Ausrichtung und gibt die Ziehdistanz in Pixeln an.

Wichtig: Dieser Modifikator ähnelt scrollable insofern, als er nur die Geste erkennt. Du musst den Zustand beibehalten und ihn auf dem Bildschirm darstellen, indem du beispielsweise das Element mit dem Modifizierer offset verschiebst:

@Composable
private fun DraggableText() {
    var offsetX by remember { mutableStateOf(0f) }
    Text(
        modifier = Modifier
            .offset { IntOffset(offsetX.roundToInt(), 0) }
            .draggable(
                orientation = Orientation.Horizontal,
                state = rememberDraggableState { delta ->
                    offsetX += delta
                }
            ),
        text = "Drag me!"
    )
}

Wenn Sie die gesamte Ziehbewegung steuern möchten, sollten Sie stattdessen die Ziehbewegungserkennung über den Modifizierer pointerInput verwenden.

@Composable
private fun DraggableTextLowLevel() {
    Box(modifier = Modifier.fillMaxSize()) {
        var offsetX by remember { mutableStateOf(0f) }
        var offsetY by remember { mutableStateOf(0f) }

        Box(
            Modifier
                .offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) }
                .background(Color.Blue)
                .size(50.dp)
                .pointerInput(Unit) {
                    detectDragGestures { change, dragAmount ->
                        change.consume()
                        offsetX += dragAmount.x
                        offsetY += dragAmount.y
                    }
                }
        )
    }
}

Ein UI-Element, das durch einen Fingerabdruck gezogen wird

Wischen

Mit dem Modifizierer swipeable können Sie Elemente ziehen, die nach der Freigabe zu zwei oder mehr Ankerpunkten in einer Ausrichtung animiert werden. Häufig wird dafür ein Muster der Wischgeste zum Schließen implementiert.

Wichtig: Dieser Modifikator verschiebt das Element nicht, sondern erkennt nur die Geste. Sie müssen den Status beibehalten und ihn auf dem Bildschirm darstellen, z. B. durch Verschieben des Elements mit dem Modifizierer offset.

Der wischbare Zustand ist im swipeable-Modifikator erforderlich und kann mit rememberSwipeableState() erstellt und gespeichert werden. Dieser Status bietet auch eine Reihe nützlicher Methoden zur programmatischen Animation von Ankern (siehe snapTo, animateTo, performFling und performDrag) sowie Attribute zur Beobachtung des Ziehfortschritts.

Die Wischgeste kann für verschiedene Schwellenwerttypen konfiguriert werden, z. B. FixedThreshold(Dp) und FractionalThreshold(Float), und diese können für jeden Ankerpunkt unterschiedlich sein.

Für mehr Flexibilität können Sie das resistance beim Wischen über die Grenzen hinaus konfigurieren. Außerdem können Sie die velocityThreshold konfigurieren, mit der ein Wischen zum nächsten Zustand animiert wird, auch wenn die Positions-thresholds noch nicht erreicht wurde.

@OptIn(ExperimentalMaterialApi::class)
@Composable
private fun SwipeableSample() {
    val width = 96.dp
    val squareSize = 48.dp

    val swipeableState = rememberSwipeableState(0)
    val sizePx = with(LocalDensity.current) { squareSize.toPx() }
    val anchors = mapOf(0f to 0, sizePx to 1) // Maps anchor points (in px) to states

    Box(
        modifier = Modifier
            .width(width)
            .swipeable(
                state = swipeableState,
                anchors = anchors,
                thresholds = { _, _ -> FractionalThreshold(0.3f) },
                orientation = Orientation.Horizontal
            )
            .background(Color.LightGray)
    ) {
        Box(
            Modifier
                .offset { IntOffset(swipeableState.offset.value.roundToInt(), 0) }
                .size(squareSize)
                .background(Color.DarkGray)
        )
    }
}

Ein UI-Element, das auf eine Wischgeste reagiert