如何在 Compose 和 coroutineScope 中对角线 animateTo?

How can I animateTo diagonally in Compose and coroutineScope?

我有一个盒子,我可以拖来拖去(很费力,但我意识到 Kotlin SDK 实际上非常好,有很多示例)。 现在。我设置这个盒子的方式是,当它被点击和移动时,它会改变它的大小——它看起来不错 :)。

现在,我想让这个盒子回到它原来的坐标(暂时是0,0,但以后会变成某个变量)。

我正在为对角线运动而苦苦挣扎。尝试了 while 循环,尝试了外部函数,以及用于计算更平滑运动的整个外部 class,但是。即使我成功向前迈出一步,它的表现也很慢!我开始认为这不是正确的方法。

@Composable
fun drawText() {
    Box(
        modifier = Modifier
            .fillMaxSize()
    ) {
        val coroutineScope = rememberCoroutineScope()
        val enable = remember { mutableStateOf(true) }
        var offsetX  =  remember { Animatable(0f) }
        var offsetY  =  remember { Animatable(0f) }
        val interactionSource = remember { MutableInteractionSource() }
        val clickable = Modifier.clickable(
            interactionSource = interactionSource,
            indication = LocalIndication.current
        ) { }
        val isPressed by interactionSource.collectIsPressedAsState()
        val size = animateSizeAsState(
            targetValue = if (enable.value && !isPressed) {
                Size(50f, 50f)
            } else {
                Size(100f, 100f)
            }
        )
        Box(
            Modifier
                .offset { IntOffset(offsetX.value.roundToInt(), offsetY.value.roundToInt()) }
                .background(Color.Blue)
                .size(size.value.width.dp, size.value.height.dp)
                .pointerInput(Unit) {
                    detectDragGestures(
                        onDragStart = {
                            enable.value = !enable.value
                        },
                        onDrag = { change, dragAmount ->
                            change.consumeAllChanges()
                            coroutineScope.launch {
                                offsetX.snapTo(offsetX.value + dragAmount.x)
                                offsetY.snapTo(offsetY.value + dragAmount.y)
                            }
                            spring(stiffness = Spring.StiffnessHigh, visibilityThreshold = 0.1.dp)

                        },
                        onDragEnd = {
                            enable.value = !enable.value
                            spring(stiffness = Spring.StiffnessLow, visibilityThreshold = 0.1.dp)
                            coroutineScope.launch {
                                offsetY.animateTo(
                                    targetValue = 0f,
                                    animationSpec = tween(
                                        durationMillis = 1000,
                                        delayMillis = 0
                                    )
                                )
                                offsetX.animateTo(
                                    targetValue = 0f,
                                    animationSpec = tween(
                                        durationMillis = 1000,
                                        delayMillis = 0
                                    )
                                )
                            }
                        }
                    )
                }
                .then(clickable)
        )
    }
}

此代码先将其移动到 0 y,然后再移动到 0 x .. 这不是我要寻找的结果

animateTo是一个suspend函数,这意味着你的X动画只有在Y动画结束时才会开始。

您可以启动另一个协程来并行 运行 它们:

coroutineScope.launch {
    launch {
        offsetY.animateTo(
            targetValue = 0f,
            animationSpec = tween(
                durationMillis = 1000,
                delayMillis = 0
            )
        )
    }
    offsetX.animateTo(
        targetValue = 0f,
        animationSpec = tween(
            durationMillis = 1000,
            delayMillis = 0
        )
    )
}

另一个选项是动画偏移量,而不是动画每个参数。以下是如何将动画与 Offset 一起使用:

val offset = remember { Animatable(Offset.Zero, Offset.VectorConverter) }

// onDrag: 
offset.snapTo(offset.value + dragAmount)

// onDragEnd:
offsetY.animateTo(
    targetValue = Offset.Zero,
    // ...