Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Jetpack Compose detect drag gesture and detect Interaction source

I want to develop a float draggable Button using jetpack compose,
also I need to know when user drag interaction starts and when it ends.

    Box(
        modifier = Modifier.fillMaxSize(),
        contentAlignment = Alignment.Center,
        content = {
            val interactionSource = remember { MutableInteractionSource() }
            val interactions = remember { mutableStateListOf<Interaction>() }
            LaunchedEffect(interactionSource) {
                interactionSource.interactions.collect { interaction ->
                    Log.i("dragInteraction", "-> $interaction")
                }
            }
            var offsetX by remember { mutableStateOf(0f) }
            var offsetY by remember { mutableStateOf(0f) }

            Surface(
                modifier = Modifier
                    .offset {
                        IntOffset(
                            x = offsetX.roundToInt(),
                            y = offsetY.roundToInt()
                        )
                    }
                    .size(60.dp)
                    .pointerInput(Unit) {
                        detectDragGestures { change, dragAmount ->
                            offsetX += dragAmount.x
                            offsetY += dragAmount.y
                            change.consume()
                        }
                    },
                interactionSource = interactionSource,
                onClick = {
                },
                content = {
                },
                color = Purple500
            )
        }
    )

in this code my Surface moves currectly but I can’t get DragInteraction.Start and
DragInteraction.Stop when I’m dragging it!
all I get is
androidx.compose.foundation.interaction.PressInteraction$Press@c38442d androidx.compose.foundation.interaction.PressInteraction$Cancel@e6d1ef3

any suggestion how can I detect drag state ?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

detectDragGestures doesn’t emit DragInteraction by default. You should either emit DragInteraction.Start, DragInteraction.Stop, DragInteraction.Cancel

as

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun DragInteractionSample() {
    Box(
        modifier = Modifier.fillMaxSize(),
        contentAlignment = Alignment.Center,
        content = {

            val interactionSource = remember { MutableInteractionSource() }
            val interactions = remember { mutableStateListOf<Interaction>() }
            var text by remember { mutableStateOf("") }

            LaunchedEffect(interactionSource) {
                interactionSource.interactions.collect { interaction ->
                    when (interaction) {
                        is DragInteraction.Start -> {
                            text = "Drag Start"
                        }
                        is DragInteraction.Stop -> {
                            text = "Drag Stop"
                        }
                        is DragInteraction.Cancel -> {
                            text = "Drag Cancel"
                        }
                    }
                }
            }

            val coroutineScope = rememberCoroutineScope()

            var offsetX by remember { mutableStateOf(0f) }
            var offsetY by remember { mutableStateOf(0f) }

            val modifier = Modifier
                .offset {
                    IntOffset(
                        x = offsetX.roundToInt(),
                        y = offsetY.roundToInt()
                    )
                }
                .size(60.dp)
                .pointerInput(Unit) {

                    var interaction: DragInteraction.Start? = null
                    detectDragGestures(
                        onDragStart = {
                            coroutineScope.launch {
                                interaction = DragInteraction.Start()
                                interaction?.run {
                                    interactionSource.emit(this)
                                }

                            }
                        },
                        onDrag = { change: PointerInputChange, dragAmount: Offset ->
                            offsetX += dragAmount.x
                            offsetY += dragAmount.y

                        },
                        onDragCancel = {
                            coroutineScope.launch {
                                interaction?.run {
                                    interactionSource.emit(DragInteraction.Cancel(this))
                                }
                            }
                        },
                        onDragEnd = {
                            coroutineScope.launch {
                                interaction?.run {
                                    interactionSource.emit(DragInteraction.Stop(this))
                                }
                            }
                        }
                    )
                }

            Surface(
                modifier = modifier,
                interactionSource = interactionSource,
                onClick = {},
                content = {},
                color = MaterialTheme.colorScheme.primary
            )

            Text(text = text)
        }
    )
}

Result

enter image description here

or simply create an enum class and set it to a MutableState on each gesture function

enum class DragState {
 Idle, DragStart, Drag, DragEnd, DragCancel
}

var dragState by remember{mutableStateOf(Idle}

And change this state on every drag callback.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading