Change progressbar color during animation

Viewed 971

I want to change my progressbar progress color based on the value of it. I have a gradient background which is created in XML.

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:id="@android:id/background">
        <shape>
            <corners android:radius="5dp"/>
            <gradient
                android:endColor="#55850000"<!-- green -->
                android:centerColor="#55e6ff00" <!-- yellow -->
                android:startColor="#5500c872" <!-- red -->
                />
        </shape>
    </item>

    <item android:id="@android:id/progress">
        <clip>
            <shape>
                <corners android:radius="5dp"/>
                <gradient
                    android:endColor="#c20600"<!-- green %100 alpha -->
                    android:centerColor="#e6ff00"<!-- yellow %100 alpha-->
                    android:startColor="#00c872"<!-- red  %100 alpha -->
                    />
            </shape>
        </clip>
    </item>

</layer-list>

My problem is this, I want to change the whole progress color based on the same of the background color.Let's say my progress comes to %60, whole progress bar should be color of yellow. If my progress comes to %90, whole progress bar should be color of red. It should change dynamically and it should be the same color with the background color of progress.



This is the animation color I used which is not working!

public class ProgressBarAnimation extends Animation{
    private ProgressBar progressBar;
    private float from;
    private float  to;

    public ProgressBarAnimation(ProgressBar progressBar, float from, float to) {
        super();
        this.progressBar = progressBar;
        this.from = from;
        this.to = to;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        super.applyTransformation(interpolatedTime, t);
        float value = from + (to - from) * interpolatedTime;
        /*if(value < 25){
            progressBar.getIndeterminateDrawable().setColorFilter(Color.GREEN, PorterDuff.Mode.MULTIPLY);
        }else if(value <=50){
            progressBar.getIndeterminateDrawable().setColorFilter(Color.YELLOW, PorterDuff.Mode.MULTIPLY);
        }else{
            progressBar.getIndeterminateDrawable().setColorFilter(Color.RED, PorterDuff.Mode.MULTIPLY);
        }*/
        // NEEDS TO CHANGE COLOR IN HERE !
        progressBar.setProgress((int) value);
    }

}
1 Answers

I did something similar recently and also had some trouble finding a simple example of this, so figured I'd share. The main difference is that I set the progress bar color on a finer-grained gradient between yellow (0%), orange (50%) and red (100%):

...
ValueAnimator valueAnimator = ValueAnimator.ofInt(currentProgress, finalProgress);
valueAnimator.setDuration(3000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {
           int[] startRGBs = getRGBColors(activity, R.color.progress_bar_yellow);
           int[] midRGBs = getRGBColors(activity, R.color.progress_bar_orange);
           int[] endRGBs = getRGBColors(activity, R.color.progress_bar_red);

           // Change the start or end colors depending on which half the progress is at (< or > 50%)
           // (done to make the transition a bit smoother, since e.g. the Blue value between orange/red is the same)
           if(percentProgressed <= 50) endRGBs = midRGBs;
           else startRGBs = midRGBs;

           int r = calcRGBValue(startRGBs[0], endRGBs[0], percentProgressed);
           int g = calcRGBValue(startRGBs[1], endRGBs[1], percentProgressed);
           int b = calcRGBValue(startRGBs[2], endRGBs[2], percentProgressed);
           int progressColorId = Color.rgb(r,g,b);

           Drawable progressDrawable = progressBar.getProgressDrawable().mutate();
           progressDrawable.setColorFilter(progressColorId, PorterDuff.Mode.MULTIPLY);
           progressBar.setProgressDrawable(progressDrawable);
        }
});

...

private int[] getRGBColors(Activity activity, int colorResourceId){
    int colorId = activity.getResources().getColor(colorResourceId);
    return new int[]{Color.red(colorId), Color.green(colorId), Color.blue(colorId)};
}

private int calcRGBValue(int startColor, int endColor, int percentProgressed){
    int colorDiff = startColor - endColor;
    if(percentProgressed > 50) percentProgressed -= 50;
    return (startColor - (int)Math.round(((double)percentProgressed ) * ((double)colorDiff / 50)));
}

So if you wanted a simple cutoff of the progress bar color at certain intervals instead of a gradient, you could ignore all of the RGB calculations above and just set the ProgressDrawable color based on the progress value:

int progressColorId;
if(progressValue < 25) progressColorId = Color.GREEN;
else if(progressValue <= 50) progressColorId = Color.YELLOW;
else progressColorId = Color.RED;

Drawable progressDrawable = progressBar.getProgressDrawable().mutate();
progressDrawable.setColorFilter(progressColorId, PorterDuff.Mode.MULTIPLY);
progressBar.setProgressDrawable(progressDrawable);
Related