Jetpack Compose 检测拖动手势并检测交互源

Moh*_*qer 1 android kotlin android-jetpack-compose compose-desktop

我想使用 jetpack compose 开发一个浮动可拖动按钮,我还需要知道用户拖动交互何时开始以及何时结束。

    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
            )
        }
    )
Run Code Online (Sandbox Code Playgroud)

在此代码中,我可以正确移动,但当我拖动它时Surface我无法得到DragInteraction.StartDragInteraction.Stop我得到的只是 androidx.compose.foundation.interaction.PressInteraction$Press@c38442d androidx.compose.foundation.interaction.PressInteraction$Cancel@e6d1ef3

有什么建议我如何检测拖动状态?

Thr*_*ian 6

默认情况下,DetectDragGestures 不会发出 DragInteraction。你应该发出DragInteraction.Start, DragInteraction.Stop,DragInteraction.Cancel

作为

@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)
        }
    )
}
Run Code Online (Sandbox Code Playgroud)

结果

在此输入图像描述

或者简单地创建一个枚举类并将其设置为每个手势函数上的 MutableState

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

var dragState by remember{mutableStateOf(Idle}
Run Code Online (Sandbox Code Playgroud)

并在每次拖动回调时更改此状态。