I have a box that I drag over and around (was a struggle, but I realised that the Kotlin SDK is actually really good with lots of examples). now. I setup this box in a way that when it's clicks, and, or moved, it changes it size - it looks nice :).
Now, I wanted this box to get back to its original coordinate (for the time being it's 0,0 but, will change to some var in the future).
I am struggling with the diagonal movement. tried while loops, tried external functions, and a whole external class for calculating the smoother movement, but. even when I succeed to go forward a step, its performing so slow!! that I am starting to think that it's not the right way.
@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)
)
}
}
This code moves it first to 0 y and than to 0 x .. which is not the outcome I'm looking for
CodePudding user response:
animateTo
is a suspend
function, which means your X animation only will start when Y animation finishes.
You can launch an other coroutine to run them in parallel:
coroutineScope.launch {
launch {
offsetY.animateTo(
targetValue = 0f,
animationSpec = tween(
durationMillis = 1000,
delayMillis = 0
)
)
}
offsetX.animateTo(
targetValue = 0f,
animationSpec = tween(
durationMillis = 1000,
delayMillis = 0
)
)
}
An other option is animating the offset, instead of animating each parameter. Here's how you can use animatable with Offset
:
val offset = remember { Animatable(Offset.Zero, Offset.VectorConverter) }
// onDrag:
offset.snapTo(offset.value dragAmount)
// onDragEnd:
offsetY.animateTo(
targetValue = Offset.Zero,
// ...