I have an existing layer-list used to customize a ProgressBar which looks like this:
style_progress_bar.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"
android:drawable="#F6F3F1" />
<item android:id="@android:id/secondaryProgress">
<scale
android:drawable="#DE0012"
android:scaleWidth="100%" />
</item>
<item android:id="@android:id/progress">
<scale
android:drawable="#DE0012"
android:scaleWidth="100%" />
</item>
</layer-list>
This layer-list is used to override a ProgressBar's progressDrawable attribute and works like a charm.
Now, I want to use the same backbone but I'd like to change the color of the second and third item programmatically, because the progress color should change in a lot of situations and creating tons of xml files is something I wouldn't do and wouldn't even be a good idea.
I managed to read the above file and read it's second and third item but I can't find a proper solution to change the color of these 2. Except the color issue, everything works as expected.
LayerDrawable layers = (LayerDrawable) getResources().getDrawable(R.drawable.style_progress_bar);
int color = getResources().getColor(colorId); // This is the ID of the new color. I use it elsewhere so this should be 100% good
layers.getDrawable(1).setColorFilter(color, PorterDuff.Mode.MULTIPLY);
layers.getDrawable(2).setColorFilter(color, PorterDuff.Mode.MULTIPLY);
// I even called invalidate(); after all this. Nothing changed
I feel like I'm really close to wrap this up but I got stuck.
Any ideas? Thanks!
Okay, I really got ahead of myself here, sorry.
Digging deeper I realized I can read the needed 2 drawable as ScaleDrawable objects because this is how they are set in the xml file, as scale.
Each of these scale items have their own drawables set:
<scale
android:drawable="#DE0012"
android:scaleWidth="100%" />
So I realized, those could be read somehow as well. And yes they can be read as ColorDrawable objects. And at the point I had my 2 ColorDrawable objects, I was able to simply set a color to these. Here is my final code to do everything:
private Drawable createDrawable(int colorId) {
LayerDrawable layers = (LayerDrawable) getResources().getDrawable(R.drawable. style_progress_bar);
int color = getResources().getColor(colorId);
try {
ScaleDrawable first = (ScaleDrawable) layers.getDrawable(1);
ScaleDrawable second = (ScaleDrawable) layers.getDrawable(2);
ColorDrawable secondaryColor = (ColorDrawable) first.getDrawable();
secondaryColor.setColor(color);
ColorDrawable primaryColor = (ColorDrawable) second.getDrawable();
primaryColor.setColor(color);
} catch (ClassCastException e) {
e.printStackTrace();
}
return layers;
}
And after this, I can simply call the above method and have my colors changed dynamically.
progressBar.setProgressDrawable(createDrawable(colorId));
Thanks, and sorry for this, but I think I'll leave the question in case somebody else gets stuck on this exceptional case when you need to use ScaleDrawable.
Be aware that using something else than scale in your xml layer-list's item, would fully color the progressView and you wouldn't get the desired result, like having a a different background color and another color for the actual progress.