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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 21:47:06