Android Compose中InfiniteTransition无限动画重启触发动作的实现方案
在Android Compose中监听InfiniteTransition动画重启的方案
你当前用InfiniteTransition实现的无限keyframes动画运行正常,但要监听每次动画重启的触发点,确实没有直接的onComplete回调可用。下面提供两种可行的实现方案:
方案一:手动控制动画循环(推荐)
放弃InfiniteTransition,改用LaunchedEffect配合animate函数手动管理动画周期,这样可以在每次动画完成(即重启前)精准触发动作:
var x by remember { mutableFloatStateOf(0.5f) } val cycleTime = 2000 // 你的动画周期时长 LaunchedEffect(Unit) { while (true) { // 执行单次keyframes动画 animate( initialValue = 0.5f, targetValue = 0.5f, // keyframes最后回到初始值,这里仅作为占位 animationSpec = keyframes { durationMillis = cycleTime 0.5f at 0 with xEasingOut 1.0f at cycleTime / 4 with xEasingBack 0.5f at cycleTime / 2 with xEasingOut 0.0f at cycleTime * 3/4 with xEasingBack 0.5f at cycleTime with xEasingOut } ) { value, _ -> x = value } // 动画完成,触发你需要的动作 // 这里就是每次动画重启前的执行点 // do something... } }
这种方式完全规避了浮点精度问题,触发时机精准,而且逻辑直观,容易维护。
方案二:监听动画值的周期节点
如果不想改动现有InfiniteTransition的代码,可以用SnapshotFlow监听动画值,结合区间判断来捕获周期结束的节点:
val infiniteTransition = rememberInfiniteTransition(label = "") val x by infiniteTransition.animateFloat( initialValue = 0.5f, targetValue = 0.0f, animationSpec = infiniteRepeatable( animation = keyframes { durationMillis = cycleTime 0.5f at 0 with xEasingOut 1.0f at cycleTime / 4 with xEasingBack 0.5f at cycleTime / 2 with xEasingOut 0.0f at cycleTime * 3/4 with xEasingBack 0.5f at cycleTime with xEasingOut }, repeatMode = RepeatMode.Restart, ), label = "x animation" ) LaunchedEffect(x) { SnapshotFlow { x } .distinctUntilChanged() // 用区间判断替代精确等于,避免浮点精度问题 .filter { it in 0.49f..0.51f } .drop(1) // 跳过初始加载时的0.5f值 .collect { // 触发动作 // do something... } }
注意:这种方式依赖动画值回到初始区间,需要根据你的动画参数调整区间范围,避免误触发。
内容的提问来源于stack exchange,提问作者dlw
相关产品推荐
相关产品推荐

