如何在 Android 中为可组合函数的出现和消失设置动画?

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

我正在制作一个自定义 Radio Button,当我从选中变为取消选中时包装动画 and/or 反之亦然。我正在使用 jetpack compose 的 AnimatedVisibility 功能,但是我没有得到预期的结果。

请注意,在上面的 gif 中,尽管按钮正常改变状态(选择到取消选择,反之亦然),但动画没有发生:

目前,尽管调用了动画函数,但此代码并未为按钮设置动画。

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
    ) {

    }
}

AnimatedVisibilityvisible 与之前和当前的重组不同时有效。在您的代码中,它始终是 true,因此不应出现动画。

在你的情况下可以使用 AnimatedContent。请注意,使用 lambda 参数对于动画功能至关重要,例如这个。

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