# Quick Trick — Use Android’s Animated Vector Drawable as ProgressBar


Preview of https://cdn.hashnode.com/res/hashnode/image/upload/v1626534581837/LrhWiqKZ1.html editing animated vector drawable (AVD).

Android’s [ProgressBar](https://developer.android.com/reference/android/widget/ProgressBar) widget comes with lot of customization controls and flexibility to set custom animated drawable. However, setting [AnimatedVectorDrawable](https://developer.android.com/reference/kotlin/android/graphics/drawable/AnimatedVectorDrawable?hl=en) is not one of the option.

So, this is a quick trick on how to use custom ImageView to create indeterminate progress indicator using Animated Vector Drawable (AVD).

```
class AvdLoadingProgressBar @JvmOverloads constructor*(
    *context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
*) *: AppCompatImageView*(*context, attrs, defStyleAttr*) {
    *private val avd = AnimatedVectorDrawableCompat.create*(*context, R.drawable.avd_anim*)*!!

    init *{
        *setImageDrawable*(*avd*)
        *avd.registerAnimationCallback*(*object : Animatable2Compat.AnimationCallback*() {
            *override fun onAnimationEnd*(*drawable: Drawable?*) {
                *post **{ **avd.start*() ***}
            ***}
        })
        *avd.start*()
    }
}*
```


```kotlin
import android.content.Context
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatImageView
import androidx.vectordrawable.graphics.drawable.Animatable2Compat
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat

/**
 * Custom loading indicator using Animated vector drawable.
 *
 * ## External Resources
 * - https://medium.com/androiddevelopers/animation-jump-through-861f4f5b3de4
 * - https://gist.github.com/nickbutcher/97143b3240682e5c5851fe45b49fde93
 * - https://medium.com/androiddevelopers/re-animation-7869722af206
 * - https://gist.github.com/nickbutcher/b1806905c6bc0ef29f545fd580935bd3
 */
class AvdLoadingProgressBar @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : AppCompatImageView(context, attrs, defStyleAttr) {
    /*
     * NOTE: It can only return null if parsing error is found.
     * So, using `!!` operator should expose any issue with the AVD XML file in API 23 or lower.
     */
    private val avd = AnimatedVectorDrawableCompat.create(context, R.drawable.avd_anim_kijiji_loading)!!

    init {
        setImageDrawable(avd)
        avd.registerAnimationCallback(object : Animatable2Compat.AnimationCallback() {
            override fun onAnimationEnd(drawable: Drawable?) {
                post { avd.start() }
            }
        })
        avd.start()
    }
}
```

```xml
<animated-vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt">
    <aapt:attr name="android:drawable">
        <vector
            android:name="vector"
            android:width="204dp"
            android:height="33dp"
            android:viewportWidth="204"
            android:viewportHeight="33">
            <group android:name="group">
                <path
                    android:name="a"
                    android:pathData="M 33 17 C 33 25.83 25.83 33 17 33 C 8.17 33 1 25.83 1 17 C 1 8.17 8.17 1 17 1 C 25.83 1 33 8.17 33 17 Z"
                    android:fillColor="#373373"
                    android:strokeWidth="1"/>
            </group>
            <group android:name="group_2">
                <path
                    android:name="b"
                    android:pathData="M 75.59 17 C 75.59 25.83 68.42 33 59.59 33 C 50.76 33 43.59 25.83 43.59 17 C 43.59 8.17 50.76 1 59.59 1 C 68.42 1 75.59 8.17 75.59 17 Z"
                    android:fillColor="#373373"
                    android:strokeWidth="1"/>
            </group>
            <group android:name="group_4">
                <path
                    android:name="c"
                    android:pathData="M 118.28 17 C 118.28 25.83 111.11 33 102.28 33 C 93.45 33 86.28 25.83 86.28 17 C 86.28 8.17 93.45 1 102.28 1 C 111.11 1 118.28 8.17 118.28 17 Z"
                    android:fillColor="#373373"
                    android:strokeWidth="1"/>
            </group>
            <group android:name="group_6">
                <path
                    android:name="d"
                    android:pathData="M 160.78 17 C 160.78 25.83 153.61 33 144.78 33 C 135.95 33 128.78 25.83 128.78 17 C 128.78 8.17 135.95 1 144.78 1 C 153.61 1 160.78 8.17 160.78 17 Z"
                    android:fillColor="#373373"
                    android:strokeWidth="1"/>
            </group>
            <group android:name="group_8">
                <path
                    android:name="e"
                    android:pathData="M 203.78 17 C 203.78 25.83 196.61 33 187.78 33 C 178.95 33 171.78 25.83 171.78 17 C 171.78 8.17 178.95 1 187.78 1 C 196.61 1 203.78 8.17 203.78 17 Z"
                    android:fillColor="#373373"
                    android:strokeWidth="1"/>
            </group>
        </vector>
    </aapt:attr>
    <target android:name="a">
        <aapt:attr name="android:animation">
            <set>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="52"
                    android:duration="100"
                    android:valueFrom="#373373"
                    android:valueTo="#f8aa17"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="650"
                    android:duration="100"
                    android:valueFrom="#f8aa17"
                    android:valueTo="#373373"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
            </set>
        </aapt:attr>
    </target>
    <target android:name="b">
        <aapt:attr name="android:animation">
            <set>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="173"
                    android:duration="100"
                    android:valueFrom="#373373"
                    android:valueTo="#f1454f"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="750"
                    android:duration="100"
                    android:valueFrom="#f1454f"
                    android:valueTo="#373373"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
            </set>
        </aapt:attr>
    </target>
    <target android:name="c">
        <aapt:attr name="android:animation">
            <set>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="300"
                    android:duration="100"
                    android:valueFrom="#373373"
                    android:valueTo="#2681db"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="850"
                    android:duration="100"
                    android:valueFrom="#2681db"
                    android:valueTo="#373373"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
            </set>
        </aapt:attr>
    </target>
    <target android:name="d">
        <aapt:attr name="android:animation">
            <set>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="424"
                    android:duration="100"
                    android:valueFrom="#373373"
                    android:valueTo="#37a864"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="950"
                    android:duration="100"
                    android:valueFrom="#37a864"
                    android:valueTo="#373373"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
            </set>
        </aapt:attr>
    </target>
    <target android:name="e">
        <aapt:attr name="android:animation">
            <set>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="550"
                    android:duration="100"
                    android:valueFrom="#373373"
                    android:valueTo="#9b44ad"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="1050"
                    android:duration="100"
                    android:valueFrom="#9b44ad"
                    android:valueTo="#373373"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
            </set>
        </aapt:attr>
    </target>
</animated-vector>

```

```text
<animated-vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt">
    <aapt:attr name="android:drawable">
        <vector
            android:name="vector"
            android:width="204dp"
            android:height="33dp"
            android:viewportWidth="204"
            android:viewportHeight="33">
            <group android:name="group">
                <path
                    android:name="a"
                    android:pathData="M 33 17 C 33 25.83 25.83 33 17 33 C 8.17 33 1 25.83 1 17 C 1 8.17 8.17 1 17 1 C 25.83 1 33 8.17 33 17 Z"
                    android:fillColor="#373373"
                    android:strokeWidth="1"/>
            </group>
            <group android:name="group_2">
                <path
                    android:name="b"
                    android:pathData="M 75.59 17 C 75.59 25.83 68.42 33 59.59 33 C 50.76 33 43.59 25.83 43.59 17 C 43.59 8.17 50.76 1 59.59 1 C 68.42 1 75.59 8.17 75.59 17 Z"
                    android:fillColor="#373373"
                    android:strokeWidth="1"/>
            </group>
            <group android:name="group_4">
                <path
                    android:name="c"
                    android:pathData="M 118.28 17 C 118.28 25.83 111.11 33 102.28 33 C 93.45 33 86.28 25.83 86.28 17 C 86.28 8.17 93.45 1 102.28 1 C 111.11 1 118.28 8.17 118.28 17 Z"
                    android:fillColor="#373373"
                    android:strokeWidth="1"/>
            </group>
            <group android:name="group_6">
                <path
                    android:name="d"
                    android:pathData="M 160.78 17 C 160.78 25.83 153.61 33 144.78 33 C 135.95 33 128.78 25.83 128.78 17 C 128.78 8.17 135.95 1 144.78 1 C 153.61 1 160.78 8.17 160.78 17 Z"
                    android:fillColor="#373373"
                    android:strokeWidth="1"/>
            </group>
            <group android:name="group_8">
                <path
                    android:name="e"
                    android:pathData="M 203.78 17 C 203.78 25.83 196.61 33 187.78 33 C 178.95 33 171.78 25.83 171.78 17 C 171.78 8.17 178.95 1 187.78 1 C 196.61 1 203.78 8.17 203.78 17 Z"
                    android:fillColor="#373373"
                    android:strokeWidth="1"/>
            </group>
        </vector>
    </aapt:attr>
    <target android:name="a">
        <aapt:attr name="android:animation">
            <set>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="52"
                    android:duration="100"
                    android:valueFrom="#373373"
                    android:valueTo="#f8aa17"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="650"
                    android:duration="100"
                    android:valueFrom="#f8aa17"
                    android:valueTo="#373373"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
            </set>
        </aapt:attr>
    </target>
    <target android:name="b">
        <aapt:attr name="android:animation">
            <set>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="173"
                    android:duration="100"
                    android:valueFrom="#373373"
                    android:valueTo="#f1454f"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="750"
                    android:duration="100"
                    android:valueFrom="#f1454f"
                    android:valueTo="#373373"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
            </set>
        </aapt:attr>
    </target>
    <target android:name="c">
        <aapt:attr name="android:animation">
            <set>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="300"
                    android:duration="100"
                    android:valueFrom="#373373"
                    android:valueTo="#2681db"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="850"
                    android:duration="100"
                    android:valueFrom="#2681db"
                    android:valueTo="#373373"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
            </set>
        </aapt:attr>
    </target>
    <target android:name="d">
        <aapt:attr name="android:animation">
            <set>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="424"
                    android:duration="100"
                    android:valueFrom="#373373"
                    android:valueTo="#37a864"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="950"
                    android:duration="100"
                    android:valueFrom="#37a864"
                    android:valueTo="#373373"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
            </set>
        </aapt:attr>
    </target>
    <target android:name="e">
        <aapt:attr name="android:animation">
            <set>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="550"
                    android:duration="100"
                    android:valueFrom="#373373"
                    android:valueTo="#9b44ad"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
                <objectAnimator
                    android:propertyName="fillColor"
                    android:startOffset="1050"
                    android:duration="100"
                    android:valueFrom="#9b44ad"
                    android:valueTo="#373373"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
            </set>
        </aapt:attr>
    </target>
</animated-vector>

```
> NOTE: The idea of repeated indefinite AVD is heavily borrowed from Nick Butcher’s medium article on AVD. I highly recommend you read them to know more tips and ticks with AVD.

That’s it. You can now use this in your layout as usual view and show it when data is loading from network or any long running async request is happening.

```
*<*androidx.constraintlayout.widget.ConstraintLayout>

  <dev.hossain.avdprogress.AvdLoadingProgressBar
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@drawable/avd_anim_kijiji_loading" />

</androidx.constraintlayout.widget.ConstraintLayout>
```


![Here is preview of the AVD in [https://shapeshifter.design/](https://shapeshifter.design/)](https://cdn-images-1.medium.com/max/2000/1*kJDC8wIDX1tV5ah4Y-xehw.gif)*Here is preview of the AVD in [https://shapeshifter.design/](https://shapeshifter.design/)*

### Further reading
[**Animation: Jump-through**
*Recently a call for help caught my eye; asking how to implement a fancy ‘getting location’ animation on Android:*medium.com](https://medium.com/androiddevelopers/animation-jump-through-861f4f5b3de4)
[**Re-animation**
*In a previous article, I described a technique for creating vector animations on Android:*medium.com](https://medium.com/androiddevelopers/re-animation-7869722af206)
