Animation / Animation Set / Interpolator / Material Design / ProgressBar

Material ProgressBar

At the time of writing I am working with the good folks at Novoda on an on-demand video streaming app for UK broadcaster Channel 4. One of the designs which I was asked to implement was a standard indeterminate ProgressBar with a material styling. While this was easy for Lollipop and later, the app needs to support earlier devices so the challenge was to come up with a lightweight approximation of the material ProgressBar which would work on older devices. In this post we’ll take a look at the solution to that problem.

Let’s first take a look at a Lollipop indeterminate ProgressBar:

While the bar styling itself is pretty easy to achieve, the problem lies in the indeterminate animation which looks rather complex. A short bar runs from left to right, but the length of this bar varies during its travel.

My first approach was to try and back-port the material indeterminate implementation. However this proved difficult because it uses an AnimatedVectorDrawable which is not available pre-Lollipop. The solution that I came up with is quite sneaky, but gives a remarkably close approximation to what we’re trying to achieve.

The solution involves creating our own ProgressBar implementation (which subclasses the standard ProgressBar) which completely bypasses the standard indeterminate logic and implements its own on top of the standard primary and secondary progress behaviours which are already built in to ProgressBar. The trick is because of how this is rendered – first the background, then the secondary progress, then the primary progress. If we have the background and the primary progress colour the same, and the secondary progress a different colour, we can give the illusion that a segment of the bar is being drawn.

An example will show this. If we set the background colour to a light green, the secondary progress colour to a mid green and the progress colour to a dark green we get this:

progress_example_1

However, if we set the primary colour to match the background colour the section of the secondary progress which is visible gives the illusion that we have drawn a segment:

progress_example_2

We can specify the start and end points of this by simply setting the secondaryProgress and progress values of the ProgressBar respectively.

So let’s take a look at how we can implement this in code:

The key method here is createIndeterminateProgressDrawable() which is replacing the layers in the LayerDrawable (which will be rendered as the ProgressBar) with those of the appropriate colours.

The other thing worth noting is that we are hardcoding this as an indeterminate ProgressBar in the constructor – this is purely to keep the example code simple and easier to understand. In the production code this has some additional code to enable the control to operate as a standard ProgressBar as well as an indeterminate one.

So now that we can draw a segment, how do we go about animating it? That bit is surprisingly easy – we animate the progress and secondary progress values of the ProgressBar, but use different interpolators for each end of the line segment which results in the segment length changing during the progress of the animation:

By making the ProgressBar a little bigger than normal, and slowing down the animation we can see this:

Let’s return it to normal dimensions and speed and compare it to a standard Lollipop indeterminate ProgressBar implementation:

They are by no means identical – the Lollipop implementation actually has a second, shorter animation phase. However, this legacy implementation is a close enough approximation to use on pre-Lollipop devices by having separate layouts the standard one containing our legacy implementation and the one in res/layout-v21 containing a standard ProgressBar.

The source code for this article is available here.

© 2015, Mark Allison. All rights reserved.

CC BY-NC-SA 4.0 Material ProgressBar by Styling Android is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Permissions beyond the scope of this license may be available at http://blog.stylingandroid.com/license-information.

Leave a Reply

Your email address will not be published. Required fields are marked *