לגרור, להחליק ולהזיז

המשתנה המשנה draggable הוא נקודת הכניסה ברמה גבוהה לתנועות גרירה בכיוון יחיד, והוא מדווח על מרחק הגרירה בפיקסלים.

חשוב לציין שהמקש הזה דומה למקש scrollable, בכך שהוא מזהה רק את המחווה. צריך לשמור את המצב ולהציג אותו במסך, למשל על ידי הזזת הרכיב באמצעות המשתנה 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!"
    )
}

אם אתם צריכים לשלוט בתנועת הגרירה כולה, מומלץ להשתמש במקום זאת בגלאי תנועת הגרירה באמצעות המקש המשתנה 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
                    }
                }
        )
    }
}

רכיב בממשק המשתמש שנגרר באמצעות לחיצה באצבע

החלקה

המשתנה המשנה swipeable מאפשר לכם לגרור רכיבים, וכשהם משוחררים הם יתנועעו באנימציה לעבר שתי נקודות עיגון או יותר, בדרך כלל לפי כיוון מסוים. שימוש נפוץ בכך הוא הטמעת דפוס של 'החלקה כדי לסגור'.

חשוב לציין שהמַעַבֵד הזה לא מזיז את הרכיב, אלא רק מזהה את התנועה. צריך לשמור את המצב ולהציג אותו במסך, למשל על ידי הזזת הרכיב באמצעות המשתנה offset.

המצב שניתן להחליק עליו נדרש במשתנה המשנה swipeable, וניתן ליצור אותו ולשמור אותו באמצעות rememberSwipeableState(). המצב הזה מספק גם קבוצה של שיטות שימושיות ליצירת אנימציה פרוגרמטית לעוגנים (ראו snapTo,‏ animateTo,‏ performFling ו-performDrag), וגם מאפיינים למעקב אחר התקדמות הגרירה.

אפשר להגדיר לסמן ההחלקה סוגים שונים של ערכי סף, כמו FixedThreshold(Dp) ו-FractionalThreshold(Float), והם יכולים להיות שונים לכל שילוב של נקודת עוגן מ-אל.

כדי לקבל גמישות רבה יותר, אפשר להגדיר את resistance כשמחליקים מעבר לגבולות, וגם את velocityThreshold שיפעיל אנימציה של החלקה למצב הבא, גם אם לא הגעתם ל-thresholds המיקומי.

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

רכיב בממשק המשתמש שמגיב לתנועת החלקה