问题
My app's minimum API-level is 19 (KitKat), and contains a layout with a horizontal ProgressBar
. I'm using android:progressTint
attribute to tint the bar to a custom color. It works pretty well on Lollipop (API 21) and above, but below (for example on API 19) it doesn't; it shows up in a different color. The reason is that this attribute
is only used in API level 21 and higher
as Android Studio states.
So I'm wondering what can be a good alternative for tinting the ProgressBar
on pre-Lollipop devices, too. Can it be made inside the layout file with XML? Or should this be done on a different way?
EDIT #1: My ProgressBar is used to show concrete values in percents, not for indicating that my layout is loading. I want to make this clear because after trying what Kuldeep Kulkarni wrote below, my bar looked like a material loading indicator (of course on the Lollipop device, not any visible result on KitKat device).
回答1:
You can wrap with ProgressBar indeterminateDrawable
method for pre-Lollipop
.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
Drawable drawableProgress = DrawableCompat.wrap(progressBar.getIndeterminateDrawable());
DrawableCompat.setTint(drawableProgress, ContextCompat.getColor(getContext(), android.R.color.holo_green_light));
progressBar.setIndeterminateDrawable(DrawableCompat.unwrap(drawableProgress));
} else {
progressBar.getIndeterminateDrawable().setColorFilter(ContextCompat.getColor(getContext(), android.R.color.holo_green_light), PorterDuff.Mode.SRC_IN);
}
回答2:
progress.getProgressDrawable().setColorFilter(color, PorterDuff.Mode.SRC_IN);
回答3:
Thanks for the suggestions from everyone! :)
The solution which works for me is to create a custom drawable XML file with the <layer-list>
root element. There, I'm defining two layer items with the native Android IDs @android:id/background
and @android:id/progress
. After this, I can define the shapes and color resources I would like to use. This solution is similar to a more popular answer on this SO question.
Content of my res/drawable/progressbar.xml
file:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="2dip" /> <!--optional-->
<gradient
android:angle="270"
android:endColor="@color/gray"
android:startColor="@color/gray" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="2dip" /> <!--optional-->
<gradient
android:angle="270"
android:endColor="@color/blue"
android:startColor="@color/blue" />
</shape>
</clip>
</item>
</layer-list>
Defined as progressDrawable
for my ProgressBar
in the layout XML file:
<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="0dp"
android:layout_height="@dimen/progress_bar_height"
android:progressDrawable="@drawable/progressbar" />
I didn't have a chance to test it below API 19, but on this level and above it works perfectly.
回答4:
This works for me
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:theme="@style/progressBarBlue" />
Then in your style.xml
define progressBarBlue
<style name="progressBarWhite" parent="@style/Theme.AppCompat">
<item name="colorAccent">@color/blue</item>
</style>
回答5:
If you want to do it programmatically, try this
public static void setSeekbarTint(SeekBar seekbar, int color) {
PorterDuff.Mode porterDuffMode = PorterDuff.Mode.SRC_IN;
if (seekbar.getIndeterminateDrawable() != null)
seekbar.getIndeterminateDrawable().setColorFilter(color, porterDuffMode);
if (seekbar.getProgressDrawable() != null &&
seekbar.getProgressDrawable() instanceof LayerDrawable) {
LayerDrawable layerDrawable = (LayerDrawable) seekbar.getProgressDrawable();
GradientDrawable gradientDrawable = (GradientDrawable) layerDrawable.findDrawableByLayerId(android.R.id.background);
layerDrawable.setColorFilter(color, porterDuffMode);
seekbar.setProgressDrawable(layerDrawable);
gradientDrawable.setColorFilter(Color.WHITE, porterDuffMode);
} else if (seekbar.getProgressDrawable() != null &&
seekbar.getProgressDrawable() instanceof ClipDrawable) {
ClipDrawable clipDrawable = (ClipDrawable) seekbar.getProgressDrawable();
clipDrawable.setColorFilter(color, porterDuffMode);
seekbar.setProgressDrawable(clipDrawable);
}
}
回答6:
I hope this will help you. Try this:
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:indeterminateTint="#F00"
android:indeterminateTintMode="src_in" />
来源:https://stackoverflow.com/questions/43251550/android-tinting-progressbar-on-pre-lollipop-devices