Tarik, geser, dan ayunkan

Pengubah draggable adalah titik entri tingkat tinggi untuk menarik gestur dalam satu orientasi, dan melaporkan jarak tarik dalam piksel.

Penting untuk diperhatikan bahwa pengubah ini mirip dengan scrollable, karena pengubah hanya mendeteksi gestur. Anda harus menyimpan status dan merepresentasikannya di layar dengan, misalnya, memindahkan elemen melalui pengubah offset:

@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!"
    )
}

Jika Anda perlu mengontrol seluruh gestur tarik, pertimbangkan untuk menggunakan detektor gestur tarik, melalui pengubah pointerInput.

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

Elemen UI sedang ditarik dengan menekan jari

Fitur Geser

Pengubah swipeable memungkinkan Anda menarik elemen yang, jika dirilis, akan cenderung bergerak ke dua atau beberapa titik link yang ditetapkan dalam orientasi. Penggunaan yang umum untuk hal ini adalah dengan menerapkan pola 'geser untuk menutup'.

Perlu diperhatikan bahwa pengubah ini tidak memindahkan elemen, tetapi hanya mendeteksi gestur. Anda perlu mempertahankan status dan menampilkannya di layar dengan, misalnya, memindahkan elemen melalui pengubah offset.

Status geser diperlukan dalam pengubah swipeable, dan dapat dibuat serta diingat dengan rememberSwipeableState(). Status ini juga menyediakan serangkaian metode yang berguna untuk secara terprogram menganimasikan ke anchor (lihat snapTo, animateTo, performFling, dan performDrag) serta properti untuk mengamati progres penarikan.

Gestur geser dapat dikonfigurasi untuk memiliki jenis nilai minimum yang berbeda, seperti FixedThreshold(Dp) dan FractionalThreshold(Float), serta keduanya dapat berbeda untuk setiap kombinasi dari-ke titik link.

Untuk fleksibilitas yang lebih besar, Anda dapat mengonfigurasi resistance saat menggeser melewati batas dan juga velocityThreshold yang akan menggerakkan geser ke status berikutnya, meskipun thresholds posisi belum tercapai.

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

Elemen UI merespons gestur geser