Android - 在 Lollipop 之前的设备上为 ProgressBar 着色

Android - Tinting ProgressBar on pre-Lollipop devices

我的应用程序的最低 API 级别是 19 (KitKat),并且包含一个水平布局 ProgressBar。我正在使用 android:progressTint 属性将栏着色为自定义颜色。它在 Lollipop (API 21) 及更高版本上运行良好,但在以下版本(例如在 API 19 上)则不然;它以不同的颜色显示。原因是这个属性

is only used in API level 21 and higher

作为 Android 工作室状态。

所以我想知道什么是在 Lollipop 之前的设备上为 ProgressBar 着色的好选择。可以用 XML 在布局文件中制作吗?还是应该以不同的方式完成?


编辑 #1: 我的 ProgressBar 用于以百分比显示具体值,而不是用于指示我的布局正在加载。我想说清楚,因为在尝试了 Kuldeep Kulkarni 在下面写的内容之后,我的栏看起来像一个 material 加载指示器(当然在 Lollipop 设备上,在 KitKat 设备上没有任何可见结果)。

希望对您有所帮助。 试试这个:

<ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:indeterminate="true"
        android:indeterminateTint="#F00"
        android:indeterminateTintMode="src_in" />

您可以使用 ProgressBar indeterminateDrawable 方法包装 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);
}

感谢大家的建议! :)

对我有用的解决方案是使用 <layer-list> 根元素创建自定义可绘制 XML 文件。在那里,我使用原生 Android ID @android:id/background@android:id/progress 定义了两层项目。在此之后,我可以定义我想要使用的形状和颜色资源。此解决方案类似于 this SO 问题上更受欢迎的答案。


我的 res/drawable/progressbar.xml 文件的内容:

<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>

在布局 XML 文件中为我的 ProgressBar 定义为 progressDrawable

<ProgressBar
        android:id="@+id/progress_bar"
        android:layout_width="0dp"
        android:layout_height="@dimen/progress_bar_height"
        android:progressDrawable="@drawable/progressbar" />

我没有机会在 API 19 以下进行测试,但在这个级别及以上它运行完美。

progress.getProgressDrawable().setColorFilter(color, PorterDuff.Mode.SRC_IN);

这对我有用

<ProgressBar
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:theme="@style/progressBarBlue" />

然后在你的style.xml定义progressBarBlue

<style name="progressBarWhite" parent="@style/Theme.AppCompat">
   <item name="colorAccent">@color/blue</item>
</style>

如果你想以编程方式进行,试试这个

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);
        }
}