animationandroid-jetpack-composeandroid-vectordrawable

Jetpack Compose: AnimatedImageVector not Animating


Please, I need help resolving this issue. I am trying to get a drawable vector to animate by rotating it. The drawable vector displays but it doesn't rotate as expected. Thanks in advance!

Below are my code snippets:

This is my drawable vector file: 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>

This is the xml file to be animated: 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%" />

This is my composable function: Composable Screen Code

@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)
            )
        }
    }
}

Solution

  • It seems that the function rememberAnimatedVectorPainter is used to finite animateion, according to the document:

    To use an AnimatedVectorDrawable resource, load up the drawable file using animatedVectorResource and pass in a boolean to switch between the start and end state of your drawable.

    In your case, the loading animation is an infinite one. So maybe just rotating the Image itself is better.

    @Composable
    // https://stackoverflow.com/questions/76025571/jetpack-compose-animatedimagevector-not-animating
    fun Q76025571(
        modifier: Modifier
    ) {
        val infiniteTransition = rememberInfiniteTransition()
        val progress by infiniteTransition.animateFloat(
            initialValue = 0f,
            targetValue = 360f,
            animationSpec = infiniteRepeatable(
                animation = tween(3000, easing = LinearEasing),
                repeatMode = RepeatMode.Restart
            )
        )
        Column(
            modifier = modifier
                .background(Color.Transparent)
                .fillMaxSize(),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Image(
                painter = painterResource(R.drawable.loading_img),
                contentDescription = "Loading Content",
                contentScale = ContentScale.Crop,
                modifier = modifier
                    .background(color = MaterialTheme.colors.background)
                    .fillMaxSize(0.5f)
                    .graphicsLayer {
                        rotationZ = progress
                    }
            )
        }
    }```