https://kotlinlang.org logo
#compose
Title
# compose
r

Rafal

11/28/2023, 9:17 AM
Is there any way to update the translationX before launching an animation? I have a segmented button that might be deselected, so if I go from the deselected state to selected state I'd like to first move the indicator behind the button, then launch a scale animation.
Copy code
var visible by remember {
    mutableStateOf(true)
}
var toggled by remember {
    mutableStateOf(false)
}

val scale by animateFloatAsState(targetValue = if (visible) 1f else 0f)
val offsetTarget = if (toggled) {
    IntOffset(xPx, 0)
} else {
    IntOffset.Zero
}
val offset by animateIntOffsetAsState(
    targetValue = offsetTarget,
    label = "offset",
    animationSpec = spring(
        dampingRatio = Spring.DampingRatioMediumBouncy,
        stiffness = Spring.StiffnessMedium
    )
)
Box(modifier = Modifier
    .graphicsLayer {
        scaleX = scale
        scaleY = scale
        translationX = offset.x.toFloat()
        translationY = offset.y.toFloat()
    }
    .fillMaxHeight()
    .width(maxWidth / 2)
    .clip(RoundedCornerShape(8.dp))
    .background(Purple)
)
I am simply combining scale and offset, but I need to be able to disable the translationX animation when I go from the invisible to visible state
otherwise it should animate
r

Ratul Sarna

11/28/2023, 10:22 AM
Would something like this work for you (I haven't been able to test it so not fully sure)?
Copy code
var visible by remember { mutableStateOf(true) }
    var toggled by remember { mutableStateOf(false) }

    val scale = remember { Animatable(0f) }
    val offset = remember { Animatable(IntOffset.Zero, IntOffset.Zero) }

    LaunchedEffect(visible) {
        scale.animateTo(
            targetValue = if (visible) 1f else 0f,
        )
    }

    LaunchedEffect(toggled) {
        if (toggled && !visible) {
            // Immediately set offset if visible is set to false
            offset.snapTo(IntOffset(xPx, 0))
        } else {
            offset.animateTo(
                targetValue = if (toggled) IntOffset(xPx, 0) else IntOffset.Zero,
                animationSpec = spring(
                    dampingRatio = Spring.DampingRatioMediumBouncy,
                    stiffness = Spring.StiffnessMedium
                )
            )
        }
    }

    Box(modifier = Modifier
    .graphicsLayer {
        scaleX = scale.value
        scaleY = scale.value
        translationX = offset.value.x.toFloat()
        translationY = offset.value.y.toFloat()
    }
    .fillMaxHeight()
    .width(maxWidth / 2)
    .clip(RoundedCornerShape(8.dp))
    .background(Purple)
    )
r

Rafal

11/30/2023, 7:04 PM
Yup! Using animatable was the way to go. Thanks! 🙇
6 Views