简体   繁体   中英

Animating between three component states in Jetpack Compose

I am familiar with the Transition API in Jetpack Compose that lets me easily animate between two states inside a Compose component.

But what would be the best way to animate between three different states?

Consider as an example a loading indicator for a component. The states could be NotLoading , Loading and HasLoaded . My thinking here would be to have a loading indicator for a component and transition between those states:

  • Transition for showing the loading indicator: NotLoading -> Loading
  • Transition for showing the data: Loading -> HasLoaded

I guess what kind of transition doesn't really matter but I was thinking first fade in loading indicator then fade out loading indicator and fade in content. But this is just an example; in reality I need to specify the transition parameters.

What would be the best way to achieve this with Jetpack Compose? Not sure if my state thinking here is the best approach for this either.

You can use the Transition API with more than 2 states - and define the individual properties of each component using animate*AsState APIs.

There is another option if you have completely different Composables, you can use the AnimatedContent APIs.

For example, the below sample uses an enum UiState , and a button to change between the states. The content is then wrapped inside the AnimatedContent() composable. By default, the initial content fades out and then the target content fades in (this behavior is called fade through).

@Composable
fun AnimatedContentStateExample() {
    Column {
        var state by remember { mutableStateOf(UiState.Loading) }
        Button(onClick = {
            state = when (state) {
                UiState.Loading -> UiState.Loaded
                UiState.Loaded -> UiState.Empty
                UiState.Empty -> UiState.Loading
            }
        }) {
            Text("Switch States")
        }
        AnimatedContent(
            targetState = state
        ) { targetState ->
            // Make sure to use `targetState`, not `state`.
            when (targetState) {
                UiState.Loading -> {
                    CircularProgressIndicator()
                }
                UiState.Loaded -> {
                    Box(
                        Modifier
                            .background(androidGreen)
                            .size(100.dp))
                    Text("Loaded")
                }
                UiState.Empty -> {
                    Box(
                        Modifier
                            .background(androidBlue)
                            .size(200.dp))
                    Text("Empty")
                }
            }
        }
    }
}

You can customize this animation behavior by specifying a ContentTransform object to the transitionSpec parameter. You can create ContentTransform by combining an EnterTransition with an ExitTransition using the with infix function. You can apply SizeTransform to the ContentTransform by attaching it with the using infix function.

More information about AnimatedContent can be found here: https://developer.android.com/jetpack/compose/animation#animatedcontent .

And samples of its usage here: https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/animation/animation/samples/src/main/java/androidx/compose/animation/samples/AnimatedContentSamples.kt

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM