Faire glisser des éléments, les faire glisser et les faire glisser d'un geste vif
Restez organisé à l'aide des collections
Enregistrez et classez les contenus selon vos préférences.
Le modificateur draggable
est le point d'entrée de niveau supérieur des gestes de déplacement dans une orientation. Il indique également la distance de déplacement en pixels.
Notez que ce modificateur est semblable à scrollable
, dans la mesure où il ne détecte que le geste. Vous devez conserver l'état et le représenter à l'écran, par exemple en déplaçant l'élément via le modificateur 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!"
)
}
Si vous devez contrôler l'ensemble du geste de déplacement, utilisez plutôt le détecteur de gestes de déplacement, avec le modificateur 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
}
}
)
}
}
Balayage
Le modificateur swipeable
vous permet de faire glisser des éléments qui, une fois relâchés, s'animent généralement vers au moins deux points d'ancrage définis dans une orientation. Cette méthode est fréquemment utilisée pour implémenter un comportement de type "balayer pour fermer la vue".
Notez que ce modificateur ne déplace pas l'élément, il détecte seulement le geste. Vous devez conserver l'état et le représenter à l'écran, par exemple en déplaçant l'élément via le modificateur offset
.
L'état de balayage est requis dans le modificateur swipeable
. Il peut être créé et mémorisé avec rememberSwipeableState()
.
Cet état fournit également un ensemble de méthodes utiles pour animer de manière automatisée les ancrages (voir snapTo
, animateTo
, performFling
et performDrag
) ainsi que des propriétés pour observer la progression du déplacement.
Il est possible de configurer différents types de seuils pour le geste de balayage, par exemple FixedThreshold(Dp)
et FractionalThreshold(Float)
, et de définir un type spécifique pour chaque combinaison de points d'ancrage de début et de fin.
Pour plus de flexibilité, vous pouvez configurer la resistance
lorsque vous balayez l'écran au-delà des limites. Vous pouvez également définir la propriété velocityThreshold
, qui animera un balayage jusqu'à l'état suivant, même si les thresholds
de position ne sont pas atteints.
@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)
)
}
}
Recommandations personnalisées
Le contenu et les exemples de code de cette page sont soumis aux licences décrites dans la Licence de contenu. Java et OpenJDK sont des marques ou des marques déposées d'Oracle et/ou de ses sociétés affiliées.
Dernière mise à jour le 2025/08/27 (UTC).
[null,null,["Dernière mise à jour le 2025/08/27 (UTC)."],[],[],null,["# Drag, swipe, and fling\n\nThe\n[`draggable`](/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.Modifier).draggable(androidx.compose.foundation.gestures.DraggableState,androidx.compose.foundation.gestures.Orientation,kotlin.Boolean,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Boolean,kotlin.coroutines.SuspendFunction2,kotlin.coroutines.SuspendFunction2,kotlin.Boolean))\nmodifier is the high-level entry point to drag gestures in a single orientation,\nand reports the drag distance in pixels.\n\nIt's important to note that this modifier is similar to `scrollable`, in that it\nonly detects the gesture. You need to hold the state and represent it on screen\nby, for example, moving the element via the\n[`offset`](/reference/kotlin/androidx/compose/foundation/layout/package-summary#(androidx.compose.ui.Modifier).offset(androidx.compose.ui.unit.Dp,%20androidx.compose.ui.unit.Dp))\nmodifier:\n\n\n```kotlin\n@Composable\nprivate fun DraggableText() {\n var offsetX by remember { mutableStateOf(0f) }\n Text(\n modifier = Modifier\n .offset { IntOffset(offsetX.roundToInt(), 0) }\n .draggable(\n orientation = Orientation.Horizontal,\n state = rememberDraggableState { delta -\u003e\n offsetX += delta\n }\n ),\n text = \"Drag me!\"\n )\n}https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/touchinput/gestures/GesturesSnippets.kt#L250-L264\n```\n\n\u003cbr /\u003e\n\nIf you need to control the whole dragging gesture, consider using the drag\ngesture detector instead, via the\n[`pointerInput`](/reference/kotlin/androidx/compose/ui/input/pointer/package-summary#(androidx.compose.ui.Modifier).pointerInput(kotlin.Any,kotlin.coroutines.SuspendFunction1))\nmodifier.\n\n\n```kotlin\n@Composable\nprivate fun DraggableTextLowLevel() {\n Box(modifier = Modifier.fillMaxSize()) {\n var offsetX by remember { mutableStateOf(0f) }\n var offsetY by remember { mutableStateOf(0f) }\n\n Box(\n Modifier\n .offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) }\n .background(Color.Blue)\n .size(50.dp)\n .pointerInput(Unit) {\n detectDragGestures { change, dragAmount -\u003e\n change.consume()\n offsetX += dragAmount.x\n offsetY += dragAmount.y\n }\n }\n )\n }\n}https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/touchinput/gestures/GesturesSnippets.kt#L268-L288\n```\n\n\u003cbr /\u003e\n\nSwiping\n-------\n\nThe\n[`swipeable`](/reference/kotlin/androidx/compose/material/package-summary#(androidx.compose.ui.Modifier).swipeable(androidx.compose.material.SwipeableState,kotlin.collections.Map,androidx.compose.foundation.gestures.Orientation,kotlin.Boolean,kotlin.Boolean,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function2,androidx.compose.material.ResistanceConfig,androidx.compose.ui.unit.Dp))\nmodifier lets you drag elements which, when released, animate towards typically\ntwo or more anchor points defined in an orientation. A common usage for this is\nto implement a 'swipe-to-dismiss' pattern.\n| **Caution:** The [`swipeable`](/reference/kotlin/androidx/compose/material/package-summary#(androidx.compose.ui.Modifier).swipeable(androidx.compose.material.SwipeableState,kotlin.collections.Map,androidx.compose.foundation.gestures.Orientation,kotlin.Boolean,kotlin.Boolean,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function2,androidx.compose.material.ResistanceConfig,androidx.compose.ui.unit.Dp)) APIs have been replaced by Foundation's [`anchoredDraggable`](/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.Modifier).anchoredDraggable(androidx.compose.foundation.gestures.AnchoredDraggableState,androidx.compose.foundation.gestures.Orientation,kotlin.Boolean,kotlin.Boolean,androidx.compose.foundation.interaction.MutableInteractionSource)) APIs in Jetpack Compose 1.6.0-alpha01.\n\nIt's important to note that this modifier does not move the element, it only\ndetects the gesture. You need to hold the state and represent it on screen by,\nfor example, moving the element via the\n[`offset`](/reference/kotlin/androidx/compose/foundation/layout/package-summary#(androidx.compose.ui.Modifier).offset(androidx.compose.ui.unit.Dp,androidx.compose.ui.unit.Dp))\nmodifier.\n\nThe swipeable state is required in the `swipeable` modifier, and can be created\nand remembered with\n[`rememberSwipeableState()`](/reference/kotlin/androidx/compose/material/package-summary#rememberSwipeableState(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Function1)).\nThis state also provides a set of useful methods to programmatically animate to\nanchors (see\n[`snapTo`](/reference/kotlin/androidx/compose/material/SwipeableState#snapTo(kotlin.Any)),\n[`animateTo`](/reference/kotlin/androidx/compose/material/SwipeableState#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec)),\n[`performFling`](/reference/kotlin/androidx/compose/material/SwipeableState#performFling(kotlin.Float)),\nand\n[`performDrag`](/reference/kotlin/androidx/compose/material/SwipeableState#performDrag(kotlin.Float)))\nas well as properties to observe the dragging progress.\n\nThe swipe gesture can be configured to have different threshold types, such as\n[`FixedThreshold(Dp)`](/reference/kotlin/androidx/compose/material/FixedThreshold#FixedThreshold(androidx.compose.ui.unit.Dp))\nand\n[`FractionalThreshold(Float)`](/reference/kotlin/androidx/compose/material/FractionalThreshold#FractionalThreshold(kotlin.Float)),\nand they can be different for each anchor point from-to combination.\n\nFor more flexibility, you can configure the `resistance` when swiping past the\nbounds and, also, the `velocityThreshold` which will animate a swipe to the\nnext state, even if the positional `thresholds`have not been reached.\n\n\n```kotlin\n@OptIn(ExperimentalMaterialApi::class)\n@Composable\nprivate fun SwipeableSample() {\n val width = 96.dp\n val squareSize = 48.dp\n\n val swipeableState = rememberSwipeableState(0)\n val sizePx = with(LocalDensity.current) { squareSize.toPx() }\n val anchors = mapOf(0f to 0, sizePx to 1) // Maps anchor points (in px) to states\n\n Box(\n modifier = Modifier\n .width(width)\n .swipeable(\n state = swipeableState,\n anchors = anchors,\n thresholds = { _, _ -\u003e FractionalThreshold(0.3f) },\n orientation = Orientation.Horizontal\n )\n .background(Color.LightGray)\n ) {\n Box(\n Modifier\n .offset { IntOffset(swipeableState.offset.value.roundToInt(), 0) }\n .size(squareSize)\n .background(Color.DarkGray)\n )\n }\n}https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/touchinput/gestures/GesturesSnippets.kt#L292-L320\n```\n\n\u003cbr /\u003e\n\nRecommended for you\n-------------------\n\n- Note: link text is displayed when JavaScript is off\n- [Understand gestures](/develop/ui/compose/touch-input/pointer-input/understand-gestures)\n- [Advanced animation example: Gestures {:#gesture-and-animation}](/develop/ui/compose/animation/advanced)\n- [Value-based animations](/develop/ui/compose/animation/value-based)"]]