androidkotlinandroid-jetpack-composeandroid-jetpack-compose-lazy-column

LazyColumn animateItemPlacement doesn't work


I have a problem, animateItemPlacement in my LazyColumn simply doesn't work, code:

val laps = stopWatchViewModel.getLapsStates().collectAsState(initial = emptyList())
LazyColumn(
    modifier = Modifier
        .fillMaxSize()
        .padding(start = 52.dp, end = 52.dp)
) {
    items(items = laps.value, key = {lap -> lap.id}) { lap ->
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(top = 12.dp, bottom = 12.dp)
                .animateItemPlacement(
                    animationSpec = tween(durationMillis = 250)
                ),
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically
        ) {
            Text(text = lap.lap, color = Color(0xff383838), fontSize = 20.sp)
            Text(text = lap.lapTime, color = Color(0xff808080), fontSize = 20.sp)
            Text(text = lap.totalTime, color = Color(0xfff7f7f7), fontSize = 20.sp)
        }
    }
}

I tried to use key = { it }(it gives an exception), tried to use key = { it.id }, tried to use key = {lap -> lap.id}. It simply doesn't want to work, but keys are unic. Also i tried to change container to the box or card. This is project on git: (https://github.com/BRBXGIT/AlarmApp). Thanks in advance


Solution

  • Finally i understand how to do this animation. The trick is that now animation of inserting or deleting something from LazyColumn is unavailable. Because if you add something to list, ui is need to be recomposed, and it doesn't support animation yet. To solve this problem, i created custom animation with Modifier.graphicsLayer. Code:

    val laps = stopWatchViewModel.getLapsStates().collectAsState(initial = emptyList())
    LazyColumn(
        modifier = Modifier
            .fillMaxSize()
            .padding(start = 52.dp, end = 52.dp)
    ) {
        items(items = laps.value) {lap ->
            var lapVisible by remember { mutableStateOf(false) }
            val animatedLapAlpha by animateFloatAsState(
                targetValue = if (lapVisible) 1f else 0f,
                label = "Lap alpha",
                animationSpec = tween(
                    durationMillis = 250,
                    easing = LinearEasing,
                )
            )
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(top = 16.dp, bottom = 16.dp)
                    .graphicsLayer {
                        lapVisible = true
                        alpha = animatedLapAlpha
                    },
                horizontalArrangement = Arrangement.SpaceBetween,
                verticalAlignment = Alignment.CenterVertically
            ) {
                Text(text = lap.lap, color = Color(0xff383838), fontSize = 20.sp)
                Text(text = lap.lapTime, color = Color(0xff808080), fontSize = 20.sp)
                Text(text = lap.totalTime, color = Color(0xfff7f7f7), fontSize = 20.sp)
            }
        }
    }
    

    P.s. Later such animations will be available with animateItemPlacement(), but not now