0

I'm working on a Jetpack Compose application where I have multiple rows of components that I want to animate simultaneously. The animation in the first row(scale) is different from the second row(CrossFade). I have achieved the concept, but the timing of both animations is different. Currently, the second animation starts only after the first animation ends. I need both animations to happen simultaneously, and after animation ends be visible for 2 seconds, and then repeat.

The desired effect I'm aiming for is illustrated below. But upon observation, you might notice that the animation isn't simultaneous.

https://jmp.sh/s/Km7SqnrBma8SRSfA3pKV

@Composable
fun <T> AnimateRotatingList(
    list: List<T>,
    modifier: Modifier = Modifier,
    animationSpec: AnimationSpec<Float> = tween(durationMillis = 2000),
    updateCurrentIndex: (Int) -> Unit,
    itemContent: @Composable (item: T) -> Unit
) {
    Box(modifier = modifier) {
        if (list.isEmpty()) return
        if (list.size == 1) {
            itemContent(list.first())
            return
        }

        var currentIndex by remember(list) { mutableIntStateOf(0) }
        val current = remember(list, currentIndex) { list[currentIndex] }
        val next = remember(list, currentIndex) { list[(currentIndex + 1) % list.size] }

        val scale = remember(list) { Animatable(1f) }

        LaunchedEffect(scale, animationSpec) {
            while (true) {
                delay(2000)
                scale.animateTo(
                    targetValue = 0f,
                    animationSpec = animationSpec,
                )
                scale.snapTo(1f)
                currentIndex = (currentIndex + 1) % list.size
                updateCurrentIndex(currentIndex)
            }
        }

        Box(modifier = Modifier.graphicsLayer {
            scaleY = scale.value
            transformOrigin = TransformOrigin(0.5f, 0f)
        }) {
            itemContent(current)
        }

        Box(modifier = Modifier.graphicsLayer {
            scaleY = 1 - scale.value
            transformOrigin = TransformOrigin(0.5f, 1f)
        }) {
            itemContent(next)
        }
    }
}

data class Event(
    val start: String,
    val end: String,
    val loc: String,
    val loca: String
)

@Composable
fun FollowEventCardHome() {
    val eventData = listOf(
        Event("A", "B", "T1", "T2"),
        Event("B", "C", "T3", "T4"),
        Event("C", "D", "T5", "T6"),
    )

    var currentIndex by remember(eventData) { mutableIntStateOf(0) }
    val current = remember(eventData, currentIndex) { eventData[currentIndex] }
    val next = remember(eventData, currentIndex) { eventData[(currentIndex + 1) % eventData.size] }

    Column {
        AnimateRotatingList(
            list = eventData,
            modifier = Modifier
                .padding(top = 150.dp),
            updateCurrentIndex = { currentIndex = it }
        ) {
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 30.dp),
                horizontalArrangement = Arrangement.SpaceBetween,
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Text(
                    text = it.start,
                    fontSize = 20.sp,
                )
                Text(
                    text = it.end,
                    fontSize = 20.sp,
                )
            }
        }

        Spacer(modifier = Modifier.padding(20.dp))

        Crossfade(targetState = currentIndex) { index ->
            val currentItem = eventData[index]
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 30.dp),
                horizontalArrangement = Arrangement.SpaceBetween,
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Text(text = current.loc)
                Text(text = current.loca)
            }
        }
    }
}

The AnimateRotatingList composable animates a list of events, rotating through them every 2 seconds. The FollowEventCardHome composable uses this to animate two rows with different animations. However, the second row starts animating only after the first row's animation ends.

How can I make both rows animate simultaneously with the same timing and repeat every 2 seconds?

Thanks in advance for any help or suggestions!

6
  • This seems to be a follow-up to stackoverflow.com/questions/78701427/… by user pepperlove.
    – Leviathan
    Commented Jul 5 at 10:17
  • If you also own the pepperlove account you can request an account merge here: stackoverflow.com/help/merging-accounts
    – Leviathan
    Commented Jul 5 at 10:24
  • @Leviathan No the two accounts are different, I am trying to achieve the same kind of animation.
    – Akhil
    Commented Jul 5 at 11:13
  • @Leviathan I saw your answer in that question. Is it possible to achieve the same I have mentioned?
    – Akhil
    Commented Jul 8 at 8:44
  • 1
    your link is invalid, please update it with a gif uploaded with stack overflow to make sure it's valid for the post life time Commented Jul 8 at 10:29

0