ObjectAnimator的repeatCount与repeatMode属性在AnimatedVector中不生效
问题原因
你的问题并非ObjectAnimator存在适配问题,不需要切换到传统Animation实现。核心原因是Jetpack Compose的animatedVectorResourceAPI本身的设计限制:该API专为单次双向状态切换动画设计,只会响应atEnd的状态变更播放一次过渡动画,会直接忽略XML中定义的repeatCount、repeatMode循环属性,因此才会出现动画仅执行一次就停止的情况。
解决方案
方案1:保留现有XML动画定义,使用原生AnimatedVectorDrawable控制
无需修改你已经编写的scale.xml、矢量图和动画矢量配置,直接在Compose中通过AndroidView包裹原生ImageView加载动画即可,XML中设置的循环属性会正常生效:
var avd: AnimatedVectorDrawable? = null AndroidView( factory = { context -> ImageView(context).apply { setImageResource(R.drawable.my_animated_vector) avd = drawable as AnimatedVectorDrawable avd?.start() } }, modifier = Modifier .size(maxWidth / (7 / 2), maxHeight / (15 / 2)) .constrainAs(moon) { top.linkTo(stars.bottom) start.linkTo(squizzelle.start, maxWidth / 13) } ) // 页面销毁时停止动画避免内存泄漏 DisposableEffect(Unit) { onDispose { avd?.stop() } }
方案2:改用Compose原生无限动画API实现(更推荐)
完全抛弃XML动画定义,使用Compose自带的无限动画API实现效果,性能更好,也更符合Compose的开发范式:
// 定义无限循环缩放动画 val infiniteTransition = rememberInfiniteTransition(label = "moon_scale_anim") val scale by infiniteTransition.animateFloat( initialValue = 1f, targetValue = 1.5f, animationSpec = infiniteRepeatable( animation = tween( durationMillis = 1000, easing = BounceEasing ), repeatMode = RepeatMode.Reverse ), label = "moon_scale_value" ) Image( painter = painterResource(id = R.drawable.ic_moon), contentDescription = "Moon", contentScale = ContentScale.Fit, modifier = Modifier .size(maxWidth / (7 / 2), maxHeight / (15 / 2)) // 应用缩放动画 .graphicsLayer { scaleX = scale scaleY = scale } .constrainAs(moon) { top.linkTo(stars.bottom) start.linkTo(squizzelle.start, maxWidth / 13) } )
注意事项
你当前矢量图中所有陨石坑的group都使用了相同的crater名称,AnimatedVectorDrawable绑定动画时默认只会作用到第一个匹配name的group。如果需要所有陨石坑都同步执行缩放,可以把所有crater group放到同一个父group中,给父group设置唯一名称,再把动画绑定到该父group即可。
内容的提问来源于stack exchange,提问作者Loïc Jackotin
相关产品推荐
相关产品推荐

