user17356317
user17356317

Reputation:

Animate the Content Changes for a particular Composable,

I have a simple Composable that shows some data to the user, and that data needs to be updated periodically. Now, I wish to add a smooth transition between data changes instead of just snapping the new data in, so that is the prime focus of this question.

Now, for a mere example, we could take a simple Image Composable. I have this

@Composable
fun ImageFrame(imagePainter: Painter){
 Box{
  Image(
   imagePainter,
   ... //Modifications, etcetra
  )
 }
}

If I want the painter to change every three seconds, how should I go about animating this change in reference to the Box with a slide-in and slide-out motion?

Upvotes: 1

Views: 2964

Answers (2)

user17356317
user17356317

Reputation:

Found a great experimental API, built into Compose for the exact same thing, it's called AnimatedContent. Here's an implementation for my use-case

@Composable
fun AnimatedImageFrame(image: Painter){
    AnimatedContent(
        targetState = image,
        transitionSpec = {
            (slideInHorizontally { -it } with slideOutHorizontally { it })
                .using(
                    // Disable clipping since the faded slide-in/out should
                    // be displayed out of bounds.
                    SizeTransform(clip = false)
                )
        }
    ) {
        Image(
            painter = it,
            contentDescription = ""
        )
    }
}

Every time you update the parameter passed to the AnimatedImageFrame, the image displayed would animate by doing a sliding motion.

To read more, refer to this doc.

Upvotes: 3

Martyna Maron
Martyna Maron

Reputation: 673

I had a similar issue, and as far as I know, the only out-of-the-box animation in Compose for content changes is Crossfade.

I ended up implementing a custom animation based on the Crossfade implementation, as it effectively will take care of managing the state for you, you'll just need to swap out the alpha value animation for slide in/out animation. Inspect the Crossfade implementation, and you'll see how it works.

The bit where Crossfade composes the new content with the fading animation is this:

    CrossfadeAnimationItem(key) {
    val alpha by transition.animateFloat(
        transitionSpec = { animationSpec }
    ) { if (it == key) 1f else 0f }
    Box(Modifier.graphicsLayer { this.alpha = alpha }) {
        content(key)
    }
}

So for sliding in/out instead, you may end up with something like:

SlideContentInAnimationItem(key) {
    transition.AnimatedVisibility(
        visible = { it == key },
        enter = slideInHorizontally( /* your animation config*/ ),
        exit = slideOutHorizontally( /* your animation config*/ )
    ) {
        content(key)
    }
}

The targetState property and the key value are one and the same - in your example it would represent your ImagePainter - if that value changes due to a state change in the composable, the Crossfade or your new custom sliding animation will be triggered.

Upvotes: 0

Related Questions