Jetpack Compose中AnimatedImageVector旋转动画不生效问题求助
Jetpack Compose矢量图旋转动画不生效问题解决
问题说明
在Jetpack Compose中尝试实现矢量图的旋转动画,矢量图可正常显示,但旋转效果无法按预期触发,以下是相关代码片段:
现有代码
矢量图文件(loading_img.xml)
<?xml version="1.0" encoding="utf-8"?> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="72" android:viewportWidth="72" android:width="24dp"> <path android:fillColor="#cccccf" android:pathData="M36.06,28.92L36.06,32.18" android:strokeColor="#e7e7e7" android:strokeLineCap="round" android:strokeWidth="1"/> <path android:fillColor="#c8c8cc" android:pathData="M39.45,29.88L37.82,32.71" android:strokeColor="#cacaca" android:strokeLineCap="round" android:strokeWidth="1"/> <path android:fillColor="#bbbbbe" android:pathData="M42.12,32.32L39.3,33.95" android:strokeColor="#cdcdcd" android:strokeLineCap="round" android:strokeWidth="1"/> <path android:fillColor="#b2b2b7" android:pathData="M39.8,35.98L43.06,35.98" android:strokeColor="#cbcbcb" android:strokeLineCap="round" android:strokeWidth="1"/> <path android:fillColor="#d0d0d4" android:pathData="M32.77,29.99L34.4,32.81" android:strokeColor="#ededed" android:strokeLineCap="round" android:strokeWidth="1"/> <path android:fillColor="#949497" android:pathData="M30.1,32.42L32.92,34.05" android:strokeColor="#525252" android:strokeLineCap="round" android:strokeWidth="1"/> <path android:fillColor="#97979b" android:pathData="M32.42,35.98L29.16,35.98" android:strokeColor="#6e6e6e" android:strokeLineCap="round" android:strokeWidth="1"/> <path android:fillColor="#a8a8ac" android:pathData="M36.06,43.08L36.06,39.82" android:strokeColor="#a0a0a0" android:strokeLineCap="round" android:strokeWidth="1"/> <path android:fillColor="#cacaca" android:pathData="M39.7,41.99L38.07,39.16" android:strokeColor="#cacaca" android:strokeLineCap="round" android:strokeWidth="1"/> <path android:fillColor="#b6b6ba" android:pathData="M42.19,39.4L39.37,37.77" android:strokeColor="#ccc" android:strokeLineCap="round" android:strokeWidth="1"/> <path android:fillColor="#a1a1a5" android:pathData="M32.46,41.98L34.09,39.16" android:strokeColor="#909090" android:strokeLineCap="round" android:strokeWidth="1"/> <path android:fillColor="#9d9da0" android:pathData="M29.85,39.4L32.67,37.77" android:strokeColor="#7a7a7a" android:strokeLineCap="round" android:strokeWidth="1"/> </vector>
动画配置文件(loading_animation.xml)
<?xml version="1.0" encoding="utf-8"?> <animated-rotate xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/loading_img" android:pivotX="50%" android:pivotY="50%" />
Compose代码
@OptIn(ExperimentalAnimationGraphicsApi::class) @Composable fun ProgressScreen(modifier: Modifier = Modifier) { Surface(modifier = modifier, color = colors.background) { val image = AnimatedImageVector.animatedVectorResource(R.drawable.loading_animation) //var atEnd by remember { mutableStateOf(false) } Column( modifier = modifier .background(TransparentBlack) .fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Image( painter = rememberAnimatedVectorPainter(image, true), contentDescription = "Loading Content", contentScale = ContentScale.Crop, modifier = modifier .background(color = colors.background) .fillMaxSize(0.5f) ) } } }
问题原因
AnimatedImageVector 和 rememberAnimatedVectorPainter 仅支持 AnimatedVectorDrawable (AVD) 格式的动画,而你使用的 <animated-rotate> 属于传统的 AnimationDrawable,两者不兼容,因此无法触发旋转效果。
解决方案
提供两种可行的解决方式:
方式一:改用AnimatedVectorDrawable实现旋转动画
修改动画配置文件为AVD格式,创建loading_avd.xml:
<?xml version="1.0" encoding="utf-8"?> <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/loading_img"> <target android:name="rotationTarget" android:animation="@anim/rotate_indefinitely" /> </animated-vector>
然后创建res/anim/rotate_indefinitely.xml:
<?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:pivotX="50%" android:pivotY="50%" android:repeatCount="infinite" android:fromDegrees="0" android:toDegrees="360" />
最后修改Compose代码,引用新的AVD文件:
@OptIn(ExperimentalAnimationGraphicsApi::class) @Composable fun ProgressScreen(modifier: Modifier = Modifier) { Surface(modifier = modifier, color = colors.background) { val image = AnimatedImageVector.animatedVectorResource(R.drawable.loading_avd) var atEnd by remember { mutableStateOf(false) } // 启动无限循环动画 LaunchedEffect(Unit) { while (true) { atEnd = !atEnd delay(1000) // 和动画时长保持一致 } } Column( modifier = modifier .background(TransparentBlack) .fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Image( painter = rememberAnimatedVectorPainter(image, atEnd), contentDescription = "Loading Content", contentScale = ContentScale.Crop, modifier = modifier .background(color = colors.background) .fillMaxSize(0.5f) ) } } }
方式二:直接在Compose中使用属性动画
无需依赖XML动画,直接用Compose的属性动画实现旋转:
@Composable fun ProgressScreen(modifier: Modifier = Modifier) { Surface(modifier = modifier, color = colors.background) { // 用animateFloatAsState实现无限旋转 val rotation by animateFloatAsState( targetValue = 360f, animationSpec = infiniteRepeatable( animation = tween(durationMillis = 1000, easing = LinearEasing) ), label = "loading rotation" ) Column( modifier = modifier .background(TransparentBlack) .fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Image( painter = painterResource(R.drawable.loading_img), contentDescription = "Loading Content", contentScale = ContentScale.Crop, modifier = modifier .background(color = colors.background) .fillMaxSize(0.5f) .rotate(rotation) // 应用旋转动画 ) } } }
说明
方式二更简洁,完全基于Compose自带的API,无需维护额外的XML文件;方式一适合复用已有的AVD动画资源。
内容的提问来源于stack exchange,提问作者Trailblazer
相关产品推荐
相关产品推荐

