Creating a Custom Loading Spinner for Android šŸ¤–

Arjun Kalburgi
Arjun Kalburgi
Published in
3 min readJan 15, 2019

Recently at Krugo, I was implementing a custom loading animation. I donā€™t usually write about work things, but this one was different.

First, the Setup

First I implemented this BehaviorSubject in my Dependency Injection:

var progressBar: BehaviorSubject<Boolean> = BehaviorSubject.createDefault(false)
fun setProgressBar(value: Boolean) {
progressBar.onNext(value)
}

And subscribed to it from the MainActivity:

Injector.progressBar.subscribeBy(
onNext = {
if
(it) {
this.mainProgress.visibility = View.VISIBLE
} else {
this.mainProgress.visibility = View.GONE
}
},onError = {})
.addTo(compositeDisposable)

These together allow me to toggle the ProgressBar view (that was set up in activity_main) simply by calling Injector.setProgressBar(true) and Injector.setProgressBar(false).

Second, the Animation

Hereā€™s the fun part. I used Shape Shifter to make the animation, this is what I made:

Shape Shifter allows you to export the animation as an animated-vector , made just for Android.

I found that breaking that animated-vector into four separate files worked best. The first is the main file, make sure your ProgressBar uses this.

<animated-vector 
android:drawable="@drawable/your_vector_file">

<target
android:name="group1"
android:animation="@anim/your_first_animation_file" />

<target
android:name="group2"
android:animation="@anim/your_second_animation_file" />
</animated-vector>

The vector file, taken from the <vector> section of the animated-vector :

<vector android:name="vector"
android:viewportWidth="1024"
android:viewportHeight="1024">
<group ... />
<group ... />
</vector>

And the two animation files taken from the <target> sections and placed under res/anim/ . Theyā€™ll look like this:

<set>
<objectAnimator ... />
<objectAnimator ... />
<objectAnimator ... />
<objectAnimator ... />
</set>

Third, Making it Work

This was all great, but it didnā€™t exactly work. The animation wouldnā€™t repeat itself after it completed. Took a while but finally got it working by doing the following:

Change ProgressBar to ImageView

<ImageView
android:contentDescription="@string/loading"
android:id="@+id/progress_bar"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center" />

Initialize the animation including registerAnimationCallback to force the looping of the animation.

val avd = AnimatedVectorDrawableCompat.create(applicationContext,          
R.drawable.your_vector_file)
findViewById<ImageView>(R.id.progress_bar).apply {
setImageDrawable(avd)
}
avd?.registerAnimationCallback(obj:Animatable2Compat.AnimationCallback() {
override fun onAnimationEnd(drawable: Drawable?) {
avd.start()
}
})

To top it off, I added start() and stop() to my subscribeBy method just to be nice:

Injector.progressBar.subscribeBy(
onNext = {
if
(it) {
this.mainProgress.visibility = View.VISIBLE
avd?.start()
} else {
this.mainProgress.visibility = View.GONE
avd?.stop()
}
},onError = {})
.addTo(compositeDisposable)

This last step took me a while to figure out but I finally got it thanks to this article from the Android Developers blog:

Overall I loved the chance to work on some animation, I think itā€™s just going to become a bigger thing in 2019 and more of a priority for me to learn!

Krugo Travel

Quick shoutout to the company Iā€™m working for, Krugo. Iā€™m working on getting the Android app up and running hence why I was doing this little animation in Android!

Have you ever been frustrated trying to plan a trip with a group of people? Maybe a bachelor party, family vacation or trip with the girls? If so, youā€™re not alone.

And weā€™ve made it our mission to help.

Krugo helps groups of friends collaboratively plan trips by finding events, buying tickets and getting a place to stay. Canā€™t wait to take my own Krugo soon šŸ˜œ

Check ā€™em out on Medium or get the app for iOS. Android coming soon!

--

--