You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose如何在动画执行中途指定时间点立即切换数值

针对当前卡片翻转场景的实现

你当前的卡片翻转动画可以直接通过rotation的数值判断完成图片切换,逻辑上完全匹配你的需求:500ms的动画中,rotationY从0到180匀速变化,当数值小于90度时显示正面,大于等于90度时显示背面,刚好对应前250ms和后250ms的分段:

Image(
    modifier = Modifier
        .fillMaxWidth()
        .padding(15.dp)
        .graphicsLayer {
            rotationY = transitionData.rotation
            cameraDistance = 8 * density
            // 可选:超过90度的时候翻转内容,避免背面图片显示为反向
            if (rotationY > 90f) {
                rotationY += 180f
            }
        },
    painter = painterResource(
        if (transitionData.rotation < 90f) {
            R.drawable.card_front // 对应你提到的资源ID1的drawable
        } else {
            R.drawable.card_back // 对应你提到的资源ID10的drawable
        }
    ),
    contentDescription = "Card",
    contentScale = FixedScale(0.7f)
)

通用的动画中途指定时间点切换值方案

如果是通用场景,需要在动画执行到指定时间点立即切换某个数值,可以用以下两种实现:

方案1:基于Transition的关键帧动画实现跳变

你可以额外加一个随Transition变化的状态,用keyframes动画规则,让它在指定时间点直接跳变,没有过渡效果:

private class TransitionData(
    rotation: State<Float>,
    // 新增切换状态,0对应前半段,1对应后半段
    showSecondState: State<Int>
) {
    val rotation by rotation
    val showSecondState by showSecondState
}

@Composable
private fun generateTransition(front: Boolean): TransitionData {
    val transition = updateTransition(front, label = "cardFlip")

    val rotation = transition.animateFloat(
        transitionSpec = { tween(500) },
        label = "rotation"
    ) { state ->
        if (state) 0f else 180f
    }

    // 新增的跳变状态,250ms时直接从0切换到1,无过渡
    val showSecondState = transition.animateInt(
        transitionSpec = {
            keyframes {
                durationMillis = 500
                0 at 0
                1 at 250 // 250ms时直接跳变到1
            }
        },
        label = "stateSwitch"
    ) { state ->
        // 目标值不影响中间跳变逻辑,只要前后状态对应即可
        if (state) 0 else 1
    }

    return remember(transition) { TransitionData(rotation, showSecondState) }
}

使用的时候直接判断showSecondState的值切换资源即可:

painter = painterResource(
    if (transitionData.showSecondState == 0) R.drawable.front else R.drawable.back
)

方案2:监听动画进度触发状态更新

如果是更复杂的触发逻辑,你可以通过snapshotFlow监听动画的进度值,到达阈值时更新本地状态:

val transitionData = generateTransition(lastCardState)
// 记录是否显示第二状态
var showSecond by remember { mutableStateOf(false) }

LaunchedEffect(transitionData.rotation) {
    snapshotFlow { transitionData.rotation }
        .collect { rotation ->
            // 当旋转超过90度(对应250ms)时更新状态
            val shouldShowSecond = rotation >= 90f
            if (showSecond != shouldShowSecond) {
                showSecond = shouldShowSecond
            }
        }
}

内容的提问来源于stack exchange,提问作者Gary Wang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 22:45:04