如何在 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,
// ...
我有一个盒子,我可以拖来拖去(很费力,但我意识到 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,
// ...