如何在Android中更改ProgressBar的进度指示器颜色

206

我设置了一个水平的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中以编程方式实现它。如果您有其他解决方案,请分享您的答案。 - Mubashar
21个回答

383

我从我的一个应用程序中复制了这个,所以可能有一些额外的属性,但应该能够给你一个想法。这是来自拥有进度条的布局:

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

接下来创建一个类似以下内容的新drawable(在这种情况下为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>

您可以根据需要更改颜色,这将为您提供绿色的进度条。


还有,我删除了这个android:indeterminate="false"。 - Nishant Shah
2
请帮帮我。我尝试通过复制你的代码创建greenprogress.xml,但是Android Studio 0.4.6标记<layer-list>为错误"Element-list must be declared",我该怎么办? - UmAnusorn
3
能否动态地更改颜色? - async
1
实际的进度条中,可以根据当前进度值更改颜色吗? - Jono
@Ryan,解释一下android:id="@android:id/progress"android:id="@android:id/background"android:id="@android:id/secondaryProgress"代表什么会很有帮助。 - RustamG
显示剩余2条评论

107

一个更简单的解决方案:

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 是一个自定义颜色。 - Nitin Saxena
2
或者 <solid android:color="@android:color/black" />,甚至是 <solid android:color="#ff33b5e5" />。 - superarts.org
2
这对于API 21及以上的足够了:android:indeterminateTint="@color/white" - GS Nayma

73

只需在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"/>

无论您的进度条是水平的还是圆形的,都不重要。

就这些。


2
哇,最简单的解决方案,对我有效。我想知道为什么这个答案有那么多赞。 - Pavel Shorokhov

50

对于API级别21或更高级别,只需使用

android:progressBackgroundTint="@color/yourBackgroundColor"
android:progressTint="@color/yourColor"

不适用于 ProgressBar。 - userVadim

41

如果你只想改变进度条的颜色,你可以在Activity的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);

灵感来自这里

只需为Android 5.0以下版本执行此操作。 在Android 5.0及以上版本中,您可以使用colorAccent样式属性。


对于 SeekBar,操作相同,只需添加 API 16:seekBar.getThumb().setColorFilter(color, PorterDuff.Mode.SRC_IN);。这将更改圆形拇指的颜色。 - Sufian
1
直接在可绘制对象上调用 setColorFilter() 方法会将颜色应用到所有地方。由于这不是我想要的,所以我只需在 Drawable 上调用 mutate() 方法(例如:seekBar.getThumb().mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);)。 - Sufian
3
我曾在别处看到过这个解决方案,但它只是(在一个Gingerbread设备上测试)把整个进度条变成了一种颜色,使得实际进度无法看到。 - Neil C. Obremski
@NeilC.Obremski 是的,你说得对。这可能是ROM特定的,或者可能是版本特定的。我不得不完全删除它。希望我们很快能将其移植回旧版Android(通过支持库)。 - Sufian

16

使用 Material Components Library,您可以使用 LinearProgressIndicator,并使用 app:indicatorColor 属性更改颜色:

  <com.google.android.material.progressindicator.LinearProgressIndicator
      app:indicatorColor="@color/..."
      app:trackThickness="..."
      app:trackColor="@color/..."
      />

输入图像描述

注意:至少需要版本1.3.0-alpha04

使用ProgressBar,您可以使用以下方法覆盖颜色:

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

使用:

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

输入图像描述


1
我建议使用这个替代标准的ProgressBar,因为它允许你在保持材料动画的同时改变轨道颜色。 - ade.se

7
有三种方法可以解决这个问题:
  1. 如何以声明的方式调整进度条的颜色
  2. 如何以编程的方式调整进度条的颜色,但从在编译时预定义的各种颜色中选择颜色
  3. 如何以编程的方式调整进度条的颜色,并且还要创建颜色程序。
特别是对于第二种和第三种方法,有很多混淆,可以看到对amfcosta回答的评论。该答案将在任何时候产生不可预测的颜色结果,除非您想将进度条设置为除主要颜色之外的任何颜色,因为它只会修改背景颜色,而实际进度条“剪辑”区域仍然是黄色叠加层并且透明度减少。例如,使用该方法将背景设置为深紫色将导致进度条“剪辑”颜色为一些疯狂的粉红色,由深紫色和黄色通过减少alpha混合而产生。
总之,Ryan完美地回答了# 1,而Štarke回答了# 3的大部分内容,但对于那些寻求# 2和# 3的完整解决方案的人:

如何以编程的方式调整进度条颜色,但从预定义的XML中选择颜色

res / drawable / my_progressbar.xml

创建此文件,但更改my_progress和my_secondsProgress中的颜色:

(注意:这只是定义默认android SDK ProgressBar的实际XML文件的副本,但我已更改了ID和颜色。原始文件名为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由LayerDrawable中的3个Drawable组成。
1.第一层是背景 2.第二层是次要进度颜色 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);

Cheers.

-Lance


在viewUtils.convertDpToPixel(5)中,viewUtils是什么? - Nikos Hidalgo
1
嗨@NikosHidalgo - 您可以在此处查看几乎相同的方法:https://dev59.com/Q2nWa4cB1Zd3GeqP1H-a。唯一的区别是我使用对“Context”的引用构建了我的`ViewUtils`,因此在调用`convertDpToPixel()`时不需要传递`Context` - lance.dolan
感谢您的及时回复,尤其是针对一个很久以前发布的答案! - Nikos Hidalgo
哈哈,我真的得使劲回忆一下才能想起来 :p - lance.dolan

5

如果您的API级别在21或以上,您可以使用以下XML属性:

<!-- For indeterminate progress bar -->
android:indeterminateTint="@color/white"
<!-- For normal progress bar -->
android:progressTint="@color/white"

4
final LayerDrawable layers = (LayerDrawable) progressBar.getProgressDrawable();
layers.getDrawable(2).setColorFilter(color,PorterDuff.Mode.SRC_IN);

1
尝试在你的答案中加入一些解释。仅提供代码的答案是不鼓励的。 - Alexei - check Codidact
我很想知道getDrawable中索引2的含义,但至少这是唯一对我有效的解决方案,所以谢谢! - Nikos Hidalgo

4
我找到的最简单的解决方案是这样的:
<item name="colorAccent">@color/white_or_any_color</item>

将上述内容放置在res > values文件夹下的styles.xml文件中。
注意:如果您使用其他强调颜色,则前面的解决方案应该适用。
API 21或更高版本。

这是最佳解决方案。100% 相关于所问的问题。非常简单。 - Pir Fahim Shah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接