How to Implement updateTransition API in Jetpack Compose

jetpack compose update transition

Today, we will learn how to implement the updateTransition API in Android Jetpack Compose.

Prerequisites:

Jetpack Compose updateTransition():

The updateTransition() API allows us to animate multiple values at a time. For this article, let’s create this UI:

jetpack compose updatetransition

When the image is small, the size is 90.dp, and the border color is green. When it gets bigger, the size and border color are changed to 130.dp, and magenta. We are animating the size and color at a time.

In the case of updateTransition, the state can be of any data type. Let’s use a custom enum type.

private enum class ImageState {
    Small, Large
}

Let’s create a variable that handles the state.

var imageState by remember {
    mutableStateOf(ImageState.Small)
}

The updateTransition() composable looks like this:

@Composable
fun <T> updateTransition(
    targetState: T,
    label: String? = null
)

It takes two parameters:

targetState – It is the state variable. When it is changed, the transition will run.

label – It is the name of the animation. We use it to differentiate the transitions in the Android Studio pane.

The updateTransition() returns a Transition object.

val transition = updateTransition(targetState = imageState, label = "BoxState Transition")

Now, we can use the transition object to call animate* functions. They help us to animate different values. The available functions are:

  • animateColor()
  • animateDp()
  • animateInt()
  • animateValue()
  • animateIntOffset()
  • animateFloat()
  • animateIntSize()
  • animateOffset()
  • animateRect()
  • animateSize()

These functions take transitionSpec and label as parameters. transitionSpec is used to specify the animation specifications and the label is used to identify the animation in the Android Studio panel.

For border color animation:

val borderColor by
transition.animateColor(label = "BoxState Color Transition") {
    when (it) {
        ImageState.Small -> Color.Green
        ImageState.Large -> Color.Magenta
    }
}

For size animation:

val size by transition.animateDp(label = "BoxState Size Transition") {
    when (it) {
        ImageState.Small -> 90.dp
        ImageState.Large -> 130.dp
    }
}

Create an Image() and set the size and border color. You can download the dog image from this link. Add a button to toggle the state.

Column(
    modifier = Modifier.fillMaxSize(),
    verticalArrangement = Arrangement.Center,
    horizontalAlignment = Alignment.CenterHorizontally
) {

    Image(
        modifier = Modifier
            .size(size = size)
            .clip(shape = CircleShape)
            .border(color = borderColor, shape = CircleShape, width = 3.dp),
        painter = painterResource(id = R.drawable.dog),
        contentDescription = "Dog"
    )

    Button(
        modifier = Modifier.padding(top = 8.dp),
        onClick = {
            imageState =
                if (imageState == ImageState.Small)
                    ImageState.Large
                else
                    ImageState.Small
        }
    ) {
        Text(text = "Toggle State")
    }
}

This is the final code:

private enum class ImageState {
    Small, Large
}

@Composable
fun MyUI() {

    var imageState by remember {
        mutableStateOf(ImageState.Small)
    }

    val transition = updateTransition(targetState = imageState, label = "BoxState Transition")

    val borderColor by
    transition.animateColor(label = "BoxState Color Transition") {
        when (it) {
            ImageState.Small -> Color.Green
            ImageState.Large -> Color.Magenta
        }
    }

    val size by transition.animateDp(label = "BoxState Size Transition") {
        when (it) {
            ImageState.Small -> 90.dp
            ImageState.Large -> 130.dp
        }
    }

    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {

        Image(
            modifier = Modifier
                .size(size = size)
                .clip(shape = CircleShape)
                .border(color = borderColor, shape = CircleShape, width = 3.dp),
            painter = painterResource(id = R.drawable.dog),
            contentDescription = "Dog"
        )

        Button(
            modifier = Modifier.padding(top = 8.dp),
            onClick = {
                imageState =
                    if (imageState == ImageState.Small)
                        ImageState.Large
                    else
                        ImageState.Small
            }
        ) {
            Text(text = "Toggle State")
        }
    }
}

Output:

jetpack compose updatetransition

Leave a Comment