Skip to content

Instantly share code, notes, and snippets.

@hossain-khan
Last active May 8, 2021 14:19
Show Gist options
  • Save hossain-khan/e44cdd3a3342d37d0f97f9ecf6321e92 to your computer and use it in GitHub Desktop.
Save hossain-khan/e44cdd3a3342d37d0f97f9ecf6321e92 to your computer and use it in GitHub Desktop.
Android custom indeterminate progress bar using ImageView and Animated Vector Drawable
<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>
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()
}
}
<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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment