Модификатор draggable() позволяет определить жесты перетаскивания на компоненте. Этот модификатор сохраняет смещение (или дельту) движения перетаскивания от исходной точки по мере его возникновения и сохраняет его в состоянии, которое создается с помощью функции rememberDraggableState(). Это состояние затем можно использовать, например, для перемещения перетаскиваемого компонента в соответствии с жестом. Определение функции модификатора:
Modifier.draggable( state: DraggableState, orientation: Orientation, enabled: Boolean = true, interactionSource: MutableInteractionSource? = null, startDragImmediately: Boolean = false, onDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit = {}, onDragStopped: suspend CoroutineScope.(velocity: Float) -> Unit = {}, reverseDirection: Boolean = false )
Параметры модификатора:
state
: состояние типа DraggableState, которое хранит информацию об операции перетаскивания.
orientation
: направоение пертаскивания. Может быть горизонтальным (значение
Orientation.Horizontal
), либо вертикальным (Orientation.Vertical
)
enabled
: доступна ли операция перетаскивания
interactionSource
: объект MutableInteractionSource, который будет использоваться для генерации DragInteraction.Start при начале перетаскивания.
startDragImmediately
: если установлено значение true, то перетаскивание начнется немедленно. Предназначено для того, чтобы конечные пользователи могли "поймать"
анимируемый компонент, нажав на него.
onDragStarted
: suspend-функция, которая вызывает при начале перетаскивания
onDragStopped
: suspend-функция, которая вызывает после завершения перетаскивания.
reverseDirection
: изменяет направление прокрутки на обратное (прокрутка сверху вниз будет вести себя как снизу вверх, а слева направо — как справа налево).
При вызове модификатора draggable() необходимо указать как минимум два параиметра - состояние перемещения и его тип - по горизонтали или по вертикали.
Рассмотрим небольшой пример:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.background import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.draggable import androidx.compose.foundation.gestures.rememberDraggableState import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import kotlin.math.roundToInt class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { var xOffset by remember { mutableStateOf(0f) } Column(Modifier.fillMaxSize()) { Box( Modifier .offset { IntOffset(xOffset.roundToInt(), 20) } .background(Color.DarkGray) .size(150.dp) .draggable( orientation = Orientation.Horizontal, state = rememberDraggableState { distance -> xOffset += distance } ) ) Text("xOffset: $xOffset", Modifier.padding(10.dp), fontSize=22.sp) } } } }
В данном случае применяется перетаскивание по горизонтали. Для его отслеживания определяем сначала состояние xOffset:
var xOffset by remember { mutableStateOf(0f) }
Для перетаскивания определяем компонент Box, x-координата которого будет привязана к состоянию xOffset:
Box( Modifier .offset { IntOffset(xOffset.roundToInt(), 20) }
Далее к этому компоненту Box применяется модификатор draggable, который использует горизонтальную ориентацию. Параметр состояния устанавливается путем вызова функции
rememberDraggableState()
, в которой концевая лямбда-выражение используется для получения текущего значения дельты перемещения для получения обновленного состояния xOffset.
Это, в свою очередь, приводит к перемещению поля в направлении жеста перетаскивания:
.draggable( orientation = Orientation.Horizontal, state = rememberDraggableState { distance -> xOffset += distance } )
И для большей наглядности определен компонент Text, который выводит значение xOffset: