Android - Tinting ProgressBar на устройствах с предустановленной Lollipop

Минимальный уровень API для моего приложения - 19 (KitKat) и содержит макет с горизонтальным ProgressBar. Я использую атрибут android:progressTint чтобы подкрасить панель к пользовательскому цвету. Он отлично работает на Lollipop (API 21) и выше, но ниже (например, на API 19) это не так; он появляется в другом цвете. Причина в том, что этот атрибут

используется только в API уровня 21 и выше

как заявляет Android Studio.

Поэтому мне интересно, что может быть хорошей альтернативой тонированию ProgressBar на устройствах с предварительным Lollipop. Может ли оно быть сделано внутри файла макета с XML? Или это должно быть сделано по-другому?


EDIT # 1: My ProgressBar используется для отображения конкретных значений в процентах, а не для указания того, что мой макет загружается. Я хочу сделать это ясно, потому что, попробовав то, что написал Kuldeep Kulkarni ниже, мой бар выглядел как индикатор загрузки материала (конечно, на устройстве Lollipop, а не на видимом результате на устройстве KitKat).

Ответ 1

Спасибо за предложения от всех! :)

Решение, которое работает для меня, заключается в создании пользовательского извлекаемого XML файла с корневым элементом <layer-list>. Там я определяю два слоя с собственными идентификаторами Android @android:id/background и @android:id/progress. После этого я могу определить формы и цветовые ресурсы, которые я хотел бы использовать. Это решение похоже на более популярный ответ на этот вопрос 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>

Определяется как progressDrawable для моего ProgressBar в XML файле макета:

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

У меня не было возможности проверить его ниже API 19, но на этом уровне и выше он отлично работает.

Ответ 2

Вы можете обмотать метод 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);
}

Ответ 3

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

Ответ 4

Это работает для меня

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

Ответ 6

Если вы хотите сделать это программно, попробуйте это

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

Ответ 7

Я надеюсь, что это поможет вам. Попробуй это:

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