Jetpack Compose - Animate recomposition on state change

291 Views Asked by At

I am having trouble animating a composable on a state change.

I have a composable that receives an object of type Interval (custom class) and List. These are dynamically generated throughout the activity usage, with a ViewModel.

How can I animate the ExerciseView recomposition when the state of interval and answerOptions change, having the old version of the composable sliding out, and the new version sliding in?

@Composable
fun ExerciseView(interval: State<Interval>, answerOptions: State<List<Int>>, audioGenerator: AudioGenerator){
    Column(
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {

        //Composable
        IntervalPlayer(
            interval.value,
            audioGenerator
        )

        //Composable
        OptionButtonList(answerOptions.value, interval.value.semitones - 1)
    }
}

I have been looking at the animation documentation, but I cannot find any information regarding custom objects state change, only for properties like visibility, color, position and scale.

Thank you in advance!

1

There are 1 best solutions below

0
On BEST ANSWER

You can do this by wrapping your content in AnimatedContent.

enter image description here

data class CustomClass(val number: Int)

@Composable
fun ExerciseScreen() {
    val customState = remember {
        mutableStateOf(CustomClass(1))
    }
    ExerciseView(customState) { customState.value = CustomClass(Random.nextInt()) }
}

@Composable
fun ExerciseView(
    customState: State<CustomClass>,
    onClick: () -> Unit,
) {
    AnimatedContent(
        targetState = customState.value,
        transitionSpec = {
            slideInHorizontally(
                initialOffsetX = { fullWidth -> fullWidth },
            ) togetherWith slideOutHorizontally(
                targetOffsetX = { fullWidth -> -fullWidth },
            )
        },
        label = "Exercise View animation",
        modifier = Modifier.fillMaxSize(),
    ) { state ->
        Column(
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally,
        ) {
            //Composable
            Button(onClick = onClick) {
                Text(text = state.number.toString())
            }
        }
    }
}