Home > Mobile >  How to animate the appearance and disappearance of a composable function in Android?
How to animate the appearance and disappearance of a composable function in Android?

Time:02-22

I'm making a custom Radio Button that wraps an animation when I go from selected to deselected and/or vice versa. I am using the AnimatedVisibility function of jetpack compose, however I am not getting the expected result.

Notice that in the gif above, despite the buttons changing state normally (selected to deselected and vice versa) the animation is not happening:

At the moment this code does not animate the buttons despite calling the animation function.

AnimatedRadioButton:

@ExperimentalAnimationApi
@Composable
fun AnimatedRadioButton(
    modifier: Modifier = Modifier,
    isSelected: Boolean,
) {
    if (isSelected)
        FadeAnimatedContainer {
            CircleOptionSelected(modifier = modifier)
        }
    else
        FadeAnimatedContainer {
            CircleOptionUnselected(modifier = modifier)
        }
}

@ExperimentalAnimationApi
@Composable
private fun FadeAnimatedContainer(
    content: @Composable AnimatedVisibilityScope.() -> Unit,
) = AnimatedVisibility(
    visible = true,
    enter = fadeIn(),
    exit = fadeOut(),
    content = content
)

CircleOptionSelected:

@Composable
fun CircleOptionSelected(
    modifier: Modifier = Modifier,
    @DimenRes ballSize: Int = R.dimen.ball_size // 24dp
) {
    val size = dimensionResource(id = ballSize)
    Box(
        modifier = modifier
            .size(size)
            .clip(CircleShape)
            .background(color = MyRed),
        contentAlignment = Alignment.Center
    ) {
        CircleOptionUnselected(ballSize = size / 2)
    }
}

CircleOptionUnselected:

private val UnselectedBallColor = Color(0xFFF2F2F2)

@Composable
fun CircleOptionUnselected(
    modifier: Modifier = Modifier,
    ballSize: Dp? = null
) {
    val size = ballSize ?: dimensionResource(id = R.dimen.ball_size)
    Surface(
        modifier = modifier.size(size),
        shape = CircleShape,
        color = UnselectedBallColor
    ) {

    }
}

CodePudding user response:

AnimatedVisibility works when visible is different between previous and current recompositions. In your code it's always true, so no animation should happen.

In your case AnimatedContent can be used. Note that using lambda parameter is critical with animation functions, like this one.

AnimatedContent(targetState = isSelected) { targetIsSelected ->
    if (targetIsSelected)
        CircleOptionSelected(modifier = modifier)
    else
        CircleOptionUnselected(modifier = modifier)
}
  • Related