Как изменить цвет индикатора прогресса ProgressBar в Android

178

Я установил горизонтальный ProgressBar.

Я хотел бы изменить цвет прогресса на желтый.

<ProgressBar 
    android:id="@+id/progressbar" 
    android:layout_width="80dip" 
    android:layout_height="20dip"  
    android:focusable="false" 
    style="?android:attr/progressBarStyleHorizontal" />

Проблема в том, что цвет выполнения у разных устройств разный. Итак, я хочу, чтобы исправить цвет прогресса.

Нишант Шах
источник
Приведенные выше ответы меняют цвет фона целиком, и это приводит к тому, что высота индикатора хода выполнения меняется на максимальную, которую невозможно изменить в XML. лучший способ изменить только статус индикатора выполнения, если количество выполненного задания составляет 20% красного цвета, 50% желтого цвета 70% и выше зеленого цвета. Вы можете сделать это программно в Java. Поделитесь своим ответом, если у вас есть другое решение.
Мубашар

Ответы:

365

Я скопировал это из одного из моих приложений, так что есть несколько дополнительных атрибутов, но они должны дать вам идею. Это из макета, который имеет индикатор выполнения:

<ProgressBar
    android:id="@+id/ProgressBar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:indeterminate="false"
    android:maxHeight="10dip"
    android:minHeight="10dip"
    android:progress="50"
    android:progressDrawable="@drawable/greenprogress" />

Затем создайте новый объект рисования с чем-то похожим на следующее (в данном случае greenprogress.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="5dip" />
            <gradient
                android:angle="270"
                android:centerColor="#ff5a5d5a"
                android:centerY="0.75"
                android:endColor="#ff747674"
                android:startColor="#ff9d9e9d" />
        </shape>
    </item>

    <item android:id="@android:id/secondaryProgress">
        <clip>
            <shape>
                <corners android:radius="5dip" />
                <gradient
                    android:angle="270"
                    android:centerColor="#80ffb600"
                    android:centerY="0.75"
                    android:endColor="#a0ffcb00"
                    android:startColor="#80ffd300" />
            </shape>
        </clip>
    </item>
    <item android:id="@android:id/progress">
        <clip>
            <shape>
                <corners android:radius="5dip" />
                <gradient
                    android:angle="270"
                    android:endColor="#008000"
                    android:startColor="#33FF33" />
            </shape>
        </clip>
    </item>

</layer-list>

Вы можете изменить цвета по мере необходимости, это даст вам зеленый индикатор выполнения.

Райан
источник
А также я удаляю этого андроида: indeterminate = "false"
Nishant Shah
2
Пожалуйста, помогите мне. Я пытаюсь создать greenprogress.xml, скопировав ваш код, но Android Studio 0.4.6 помечает <layer-list> as и выдает ошибку "Element-list", что мне делать?
UmAnusorn
1
Можно ли динамически менять цвет?
async
Можно ли изменить цвет в зависимости от текущего значения прогресса, определенного на фактической панели?
Джонатан
@ Райан Было бы полезно объяснить, что android:id="@android:id/progress", android:id="@android:id/background"и android:id="@android:id/secondaryProgress"поддержать.
РустамГ
103

Более простое решение:

progess_drawable_blue

<?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>
        <solid
                android:color="@color/disabled" />
    </shape>
</item>

<item
    android:id="@android:id/progress">
    <clip>
        <shape>
            <solid
                android:color="@color/blue" />
        </shape>
    </clip>
</item>

</layer-list>
Нитин Саксена
источник
1
здесь @ color / disabled - это пользовательский цвет
Нитин Саксена
2
Или <solid android: color = "@ android: color / black" />, или даже <solid android: color = "# ff33b5e5" />
superarts.org
2
Этого достаточно для андроида: indeterminateTint = "@ color / white" для рычага API 21 и выше
Ghanshyam Nayma
53

Просто создайте стиль в values/styles.xml.

<style name="ProgressBarStyle">
    <item name="colorAccent">@color/greenLight</item>
</style>

Затем установите этот стиль в качестве ProgressBarтемы.

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

и не имеет значения, ваш индикатор прогресса является горизонтальным или круглым. Вот и все.

Али Зейнали
источник
1
Ничего себе, самое простое решение, работает для меня. Я задавался вопросом, почему у этого ответа так много голосов.
Павел Шорохов
38

Если вы хотите изменить только цвет индикатора выполнения, вы можете просто использовать цветной фильтр в методе onCreate () вашей деятельности:

ProgressBar progressbar = (ProgressBar) findViewById(R.id.progressbar);
int color = 0xFF00FF00;
progressbar.getIndeterminateDrawable().setColorFilter(color, PorterDuff.Mode.SRC_IN);
progressbar.getProgressDrawable().setColorFilter(color, PorterDuff.Mode.SRC_IN);

Идея отсюда .

Вам нужно сделать это только для версий перед леденцом на палочке. В Lollipop вы можете использовать атрибут стиля colorAccent.

amfcosta
источник
Для SeekBarэто то же самое, просто добавьте к API 16: seekBar.getThumb().setColorFilter(color, PorterDuff.Mode.SRC_IN);. Это изменит цвет этого круглого пальца.
Суфий
1
Вызов setColorFilter()на рисование напрямую будет применять цвет везде. Поскольку это то , что мне не нужно, я просто позвонил mutate()на Drawable(то есть какseekBar.getThumb().mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
Sufian
3
Я видел это решение в другом месте, но все, что он делает (тестирование на устройстве Gingerbread), это поворачивает весь индикатор выполнения на один цвет, делая невозможным увидеть фактический прогресс
Нил С. Обремски,
@ NeilC.Обремски да, ты прав. Это может быть характерно для ПЗУ или версии. Я должен был удалить это вообще. Надеюсь, мы скоро перенесем это на более старые версии Android (через поддержку lib).
Суфиан
25

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

android:progressBackgroundTint="@color/yourBackgroundColor"
android:progressTint="@color/yourColor"
Мухаммед Мусави
источник
6

Есть 3 способа решить этот вопрос:

  1. Как правильно настроить цвет индикатора выполнения
  2. Как программно настроить цвет индикатора выполнения, но выбрать цвет из различных предопределенных цветов, объявленных до компиляции
  3. Как настроить цвет индикатора выполнения программно, а также создать цвет программно.

В частности, существует много путаницы вокруг # 2 и # 3, как видно из комментариев к ответу amfcosta. Этот ответ даст непредсказуемые цветовые результаты в любое время, когда вы захотите установить индикатор выполнения на что угодно, кроме основных цветов, так как он только изменяет цвет фона, а фактическая область «клипа» индикатора выполнения все равно будет наложена желтым цветом с уменьшенной непрозрачностью. Например, использование этого метода для установки темно-фиолетового фона приведет к тому, что индикатор выполнения «обрезает» какой-то сумасшедший розоватый цвет в результате смешивания темно-фиолетового и желтого цветов с помощью уменьшенного альфа-канала.

Так или иначе, Райан отлично отвечает на вопрос № 1, а Штарке отвечает на большинство вопросов № 3, но для тех, кто ищет полное решение для № 2 и № 3:


Как программно настроить цвет индикатора выполнения, но выбрать цвет из предварительно определенного цвета, объявленного в XML

res / drawable / my_progressbar.xml :

Создайте этот файл, но измените цвета в my_progress и my_secondsProgress:

(ПРИМЕЧАНИЕ. Это просто копия фактического файла XML, определяющего SDK ProgressBar по умолчанию для Android, но я изменил идентификаторы и цвета. Оригинал называется progress_horizontal)

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

<item android:id="@+id/my_progress_background">
    <shape>
        <corners android:radius="5dip" />
        <gradient
            android:startColor="#ff9d9e9d"
            android:centerColor="#ff5a5d5a"
            android:centerY="0.75"
            android:endColor="#ff747674"
            android:angle="270"
            />
    </shape>
</item>

<item android:id="@+id/my_secondaryProgress">
    <clip>
        <shape>
            <corners android:radius="5dip" />
            <gradient
                android:startColor="#80ff171d"
                android:centerColor="#80ff1315"
                android:centerY="0.75"
                android:endColor="#a0ff0208"
                android:angle="270"
                />
        </shape>
    </clip>
</item>

<item android:id="@+id/my_progress">
    <clip>
        <shape>
            <corners android:radius="5dip" />
            <gradient
                android:startColor="#7d2afdff"
                android:centerColor="#ff2afdff"
                android:centerY="0.75"
                android:endColor="#ff22b9ba"
                android:angle="270"
                />
        </shape>
    </clip>
</item>

В вашей Java :

final Drawable drawable;
int sdk = android.os.Build.VERSION.SDK_INT;
    if(sdk < 16) {
        drawable =  ctx.getResources().getDrawable(R.drawable.my_progressbar);
    } else {
        drawable = ContextCompat.getDrawable(ctx, R.drawable.my_progressbar);
    }
progressBar.setProgressDrawable(drawable)

Как программно настроить цвет индикатора выполнения, а также создать цвет программно

РЕДАКТИРОВАТЬ: я нашел время, чтобы решить это правильно. Мой прежний ответ оставил это немного двусмысленным.

ProgressBar состоит из 3 Drawables в LayerDrawable.

  1. Слой 1 является фоном
  2. Слой 2 является вторичным цветом прогресса
  3. Слой 3 - основной цвет индикатора выполнения

В приведенном ниже примере я поменяю цвет основного индикатора на голубой.

//Create new ClipDrawable to replace the old one
float pxCornerRadius = viewUtils.convertDpToPixel(5);
final float[] roundedCorners = new float[] { pxCornerRadius, pxCornerRadius, pxCornerRadius, pxCornerRadius, pxCornerRadius, pxCornerRadius, pxCornerRadius, pxCornerRadius };
ShapeDrawable shpDrawable = new ShapeDrawable(new RoundRectShape(roundedCorners, null, null));
shpDrawable.getPaint().setColor(Color.CYAN);
final ClipDrawable newProgressClip = new ClipDrawable(shpDrawable, Gravity.LEFT, ClipDrawable.HORIZONTAL);

//Replace the existing ClipDrawable with this new one
final LayerDrawable layers = (LayerDrawable) progressBar.getProgressDrawable();
layers.setDrawableByLayerId(R.id.my_progress, newProgressClip);

Этот пример установил его на сплошной цвет. Вы можете установить его в градиентный цвет, заменив

shpDrawable.getPaint().setColor(Color.CYAN);

с участием

Shader shader = new LinearGradient(0, 0, 0, progressBar.getHeight(), Color.WHITE, Color.BLACK, Shader.TileMode.CLAMP);
shpDrawable.getPaint().setShader(shader);

Приветствия.

-Lance

lance.dolan
источник
что такое viewUtils в viewUtils.convertDpToPixel (5);
Никос Идальго
1
Привет @NikosHidalgo - Вы можете увидеть почти идентичный метод здесь: stackoverflow.com/questions/12849366/… . Единственное отличие состоит в том , что я ViewUtilsContextContextconvertDpToPixel()
создаю
Спасибо за ваш быстрый ответ, особенно за ответ, который был опубликован так давно!
Никос Идальго
Ха-ха, мне действительно пришлось
напрячь
4

Если вы находитесь на уровне API 21 или выше, вы можете использовать эти атрибуты XML:

<!-- For indeterminate progress bar -->
android:indeterminateTint="@color/white"
<!-- For normal progress bar -->
android:progressTint="@color/white"
Ганшьям Найма
источник
3

Самое простое решение, которое я обнаружил, выглядит примерно так:

<item name="colorAccent">@color/white_or_any_color</item>

Поместите выше в styles.xmlфайл в res > valuesпапке.

ПРИМЕЧАНИЕ. Если вы используете какой-либо другой акцентный цвет, лучше использовать предыдущие решения.

API 21 или выше

Sazid
источник
Это лучшее решение. 100% связано с заданным вопросом. очень просто
Пир Фахим Шах
3
final LayerDrawable layers = (LayerDrawable) progressBar.getProgressDrawable();
layers.getDrawable(2).setColorFilter(color,PorterDuff.Mode.SRC_IN);
user3135773
источник
1
Попробуйте добавить небольшое объяснение к вашему ответу. Код только ответы не рекомендуется.
Алексей
Я бы хотел получить объяснение индекса 2 в getDrawable, но, по крайней мере, это было единственное решение, которое сработало для меня, так что спасибо!
Никос Идальго
2

Для тех, кто ищет, как это сделать программно:

    Drawable bckgrndDr = new ColorDrawable(Color.RED);
    Drawable secProgressDr = new ColorDrawable(Color.GRAY);
    Drawable progressDr = new ScaleDrawable(new ColorDrawable(Color.BLUE), Gravity.LEFT, 1, -1);
    LayerDrawable resultDr = new LayerDrawable(new Drawable[] { bckgrndDr, secProgressDr, progressDr });
    //setting ids is important
    resultDr.setId(0, android.R.id.background);
    resultDr.setId(1, android.R.id.secondaryProgress);
    resultDr.setId(2, android.R.id.progress);

Установка идентификаторов для drawables имеет решающее значение, и заботится о сохранении границ и фактического состояния индикатора выполнения

STARKE
источник
1

Вы, ребята, действительно причиняете мне головную боль. Что вы можете сделать, это сделать свой список слоев пригодным для рисования через XML сначала (имеется в виду фон в качестве первого слоя, чертеж, представляющий вторичный прогресс в качестве второго слоя, и другой чертеж, представляющий основной прогресс в качестве последнего слоя), а затем изменить цвет на коде, выполнив следующее:

public void setPrimaryProgressColor(int colorInstance) {
      if (progressBar.getProgressDrawable() instanceof LayerDrawable) {
        Log.d(mLogTag, "Drawable is a layer drawable");
        LayerDrawable layered = (LayerDrawable) progressBar.getProgressDrawable();
        Drawable circleDrawableExample = layered.getDrawable(<whichever is your index of android.R.id.progress>);
        circleDrawableExample.setColorFilter(colorInstance, PorterDuff.Mode.SRC_IN);
        progressBar.setProgressDrawable(layered);
    } else {
        Log.d(mLogTag, "Fallback in case it's not a LayerDrawable");
        progressBar.getProgressDrawable().setColorFilter(color, PorterDuff.Mode.SRC_IN);
    }
}

Этот метод даст вам максимальную гибкость, позволяя измерить исходный чертеж, объявленный в xml, БЕЗ МОДИФИКАЦИИ ПОСЛЕ ТОГО, КАК ЕГО СТРУКТУРА, особенно если вам нужна конкретная папка экрана xml, а затем просто измените ТОЛЬКО ЦВЕТ через код. Никакого повторного создания нового ShapeDrawable с нуля.

Пирс Бетос
источник
1

Цвет ProgressBar можно изменить следующим образом:

/res/values/colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorAccent">#FF4081</color>
</resources>

/res/values/styles.xml

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="colorAccent">@color/colorAccent</item>
</style> 

OnCreate:

progressBar = (ProgressBar) findViewById(R.id.progressBar);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
    Drawable drawable = progressBar.getIndeterminateDrawable().mutate();
    drawable.setColorFilter(ContextCompat.getColor(this, R.color.colorAccent), PorterDuff.Mode.SRC_IN);
    progressBar.setIndeterminateDrawable(drawable);
}
Милан Глинак
источник
1

Создайте нарисованный ресурс, какой фон вам нужен, в моем случае я назвал его bg_custom_progressbar.xml

<?xml version="1.0" encoding="utf-8"?>

<item>
    <shape android:shape="rectangle" >
        <corners android:radius="5dp"/>

        <gradient
            android:angle="180"
            android:endColor="#DADFD6"
            android:startColor="#AEB9A3" />
    </shape>
</item>
<item>
    <clip>
        <shape android:shape="rectangle" >
            <corners android:radius="5dp" />

            <gradient
                android:angle="180"
                android:endColor="#44CF4A"
                android:startColor="#2BB930" />
        </shape>
    </clip>
</item>
<item>
    <clip>
        <shape android:shape="rectangle" >
            <corners android:radius="5dp" />

            <gradient
                android:angle="180"
                android:endColor="#44CF4A"
                android:startColor="#2BB930" />
        </shape>
    </clip>
</item>

Затем используйте этот пользовательский фон, как

 <ProgressBar
                android:id="@+id/progressBarBarMenuHome"
                style="?android:attr/progressBarStyleHorizontal"
                android:layout_width="match_parent"
                android:layout_height="20dp"
                android:layout_marginStart="10dp"
                android:layout_marginEnd="10dp"
                android:layout_marginBottom="6dp"
                android:indeterminate="false"
                android:max="100"
                android:minWidth="200dp"
                android:minHeight="50dp"
                android:progress="10"
                android:progressDrawable="@drawable/bg_custom_progressbar" />

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

М-р Джуел Рана
источник
0

В xml:

<ProgressBar
                    android:id="@+id/progressBar"
                    style="?android:attr/progressBarStyleInverse"
                    android:layout_width="60dp"
                    android:layout_height="60dp"
                    android:layout_margin="@dimen/dimen_10dp"


                 android:indeterminateTint="@{viewModel.getComplainStatusUpdate(position)}"
                    android:indeterminate="true"
                    android:indeterminateOnly="false"
                    android:max="100"
                    android:clickable="false"
                    android:indeterminateDrawable="@drawable/round_progress"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintLeft_toLeftOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />

ViewModel:

fun getComplainStatusUpdate(position: Int):Int{

                val list = myAllComplainList!!.getValue()
                if (list!!.get(position).complainStatus.equals("P")) {
                  //  progressBar.setProgressTintList(ColorStateList.valueOf(Color.RED));
                   // progressBar.setBackgroundResource(R.drawable.circle_shape)
                    return Color.RED
                } else if (list!!.get(position).complainStatus.equals("I")) {

                    return Color.GREEN
                } else {

                    return Color.GREEN
                }


return Color.CYAN
    }
Soumen Das
источник
0

В библиотеке компонентов материалов вы можете использовать атрибут ProgressIndicatorwith app:indicatorColorдля изменения цвета:

  <com.google.android.material.progressindicator.ProgressIndicator
      style="@style/Widget.MaterialComponents.ProgressIndicator.Linear.Determinate"
      app:indicatorColor="@color/..."
      app:indicatorWidth="..."
      app:trackColor="@color/..."
      />

введите описание изображения здесь

Примечание : требуется как минимум версия 1.3.0-alpha01.

С помощью ProgressBarвы можете переопределить цвет используя:

<ProgressBar
    android:theme="@style/CustomProgressBarTheme"
    ..>

с участием:

<style name="CustomProgressBarTheme">
    <item name="colorAccent">@color/primaryDarkColor</item>
</style>

введите описание изображения здесь

Габриэле Мариотти
источник
0

Если вы хотите программно установить основной и дополнительный цвет хода для горизонтального индикатора выполнения в Android, используйте фрагмент ниже

int[][] states = new int[][] {
                        new int[] {-android.R.attr.state_checked},
                        new int[] {android.R.attr.state_checked},
                };

                int[] secondaryColor = new int[] {
                        context.getResources().getColor(R.color.graph_line_one),
                        Color.RED,
                };

                int[] primaryColor = new int[] {
                        context.getResources().getColor(R.color.middle_progress),
                        Color.BLUE,
                };
                progressbar.setProgressTintList(new ColorStateList(states, primaryColor));
                progressbar.setSecondaryProgressTintList(new ColorStateList(states, secondaryColor));
Рахул Камбл
источник