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

Ilan Sasportas

04/12/2023, 1:31 PM
Hello ! I’m trying to use
AnimatedContent
to animate my content between each type of state.
Copy code
@Composable
fun MyComposable(content: MyState, modifier: Modifier) {
    AnimatedContent(
        targetState = content,
        transitionSpec = { fadeIn(animationSpec = tween(500)) with fadeOut(animationSpec = tween(500)) }
    ) { targetState, contentModifier ->
        when (targetState) {
            is MyState.Loading -> LoadingContent(contentModifier)

            is MyState.Success -> SuccessContent(
                model = targetState.successModel,
                modifier = contentModifier
            )

            is MyState.Error -> ErrorContent(
                model = targetState.errorModel,
                modifier = contentModifier
            )
        }
    }
}
Unfortunately the animation is triggered at each state change, even between 2 Success for instance, which I don’t want. Any idea how can I trigger animation only between Loading / Success / Error types ?
t

Thomas Urbanitsch

04/12/2023, 2:00 PM
within the transitionSpec you should be able to compare the initialState and the targetState and only perform the transition if they are i haven’t used AnimatedContent yet, but i can only assume that the idea is to not be called if the state doesn’t change, so it might also help to take a look at the type you are using as State
j

Joel Denke

04/12/2023, 2:01 PM
Make sure MyState is @Stable both avoid recomposition overall and new animation triggers. Could also if its a Flow using distinctUntilChanged.
Can do custom comparable / equals override check if both is Success, both Error of each state treat as no change.
i

Ilan Sasportas

04/12/2023, 2:02 PM
yep @Thomas Urbanitsch I tried this but it doesn’t prevent the AnimatedContent to trigger the transition, it just removes the animation ... (it breaks the ui, like lazylistState and all)
The thing I want is not prevent recomposition, because if I retrigger a success on a previous success, I do want to display the changes. The thing I don’t want is retrigger the animation. I suppose that with overriding equals, I might break that mechanism, or may be I don’t exactly see where you would put it ?
o

Oleksandr Balan

04/12/2023, 2:16 PM
I think you should use
contentKey
. However it is not available in
AnimatedContent
without a receiver, don’t know why 🤔 But you could create own
transition
and use extension function
AnimatedContent
. I would specify a state class as a key, this should not animate between success states.
Copy code
val content: MyState = ...
val transition = updateTransition(targetState = content)
transition.AnimatedContent(
    contentKey = { content.javaClass }
) {
}
j

Joel Denke

04/12/2023, 2:17 PM
You should be able to compare only for animatedContent as well. I guess want MyComposable trigger recomposition but not animation part. Should be able to skip animation in transitionSpec as @thomas mention by compare initial and target state.
i

Ilan Sasportas

04/12/2023, 2:26 PM
Oh wow thanks @Oleksandr Balan it seems to work !
Thank you all for your help !
d

Doris Liu

04/12/2023, 6:19 PM
We initially thought
contentKey
would be serving for an uncommon use case, which is why it is not a part of the AnimatedContent API without receiver to avoid confusion. But it seems the need for it is more common than we initially thought. 🙂 I'll look into adding it to all the AnimatedContent APIs
i

Ilan Sasportas

04/12/2023, 6:21 PM
Thanks for the insight Doris, would be a great addition
121 Views