ChatGPT解决这个技术问题 Extra ChatGPT

How to change ProgressBar's progress indicator color in Android

I have set Horizontal ProgressBar.

I would like to change the progress color to yellow.

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

The problem is, the progress color is different in different devices. So, I want it to fix the progress color.

above answers change the whole background color and it's ambigios that it change the height of progress bar to very max.which unable to change in xml. better way to change only progress bar status that how much is completed i.s 20% red color, 50% yellow color 70% and above green color. you can do it programmatically in java. share your answer if you have any other solution.

B
Boken

I copied this from one of my apps, so there's prob a few extra attributes, but should give you the idea. This is from the layout that has the progress bar:

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

Then create a new drawable with something similar to the following (In this case 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>

You can change up the colors as needed, this will give you a green progress bar.


And also i remove this android:indeterminate="false"
Please help me. I try to create greenprogress.xml by copy your code but the Android Studio 0.4.6 mark as and error "Element-list must be declared" what should I do?
Is it possible to change the colour dynamically?
can the colour be changed depending on current progress value defined in the actual bar?
@Ryan It would be helpful to explain what android:id="@android:id/progress", android:id="@android:id/background" and android:id="@android:id/secondaryProgress" stand for.
N
Nitin Saxena

A simpler solution:

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>

here @color/disabled is a custom color
Or , or even
This is enough android:indeterminateTint="@color/white" for API lever 21 and above
a
alizeyn

Just create a style in values/styles.xml.

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

Then set this style as your ProgressBar theme.

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

and doesn't matter your progress bar is horizontal or circular. That's all.


Wow, the simpliest solution, works for me. I wondered why this answer has so many votes.
M
Mohammad Mousavi

for API level 21 or higher just use

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

a
amfcosta

If you only want to change the progress bar color, you can simply use a color filter in your Activity's onCreate() method:

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

Idea from here.

You only need to do this for pre-lollipop versions. On Lollipop you can use the colorAccent style attribute.


For SeekBar it is the same, just add for API 16: seekBar.getThumb().setColorFilter(color, PorterDuff.Mode.SRC_IN);. This will change the colour of that round thumb.
Calling setColorFilter() on a drawable directly will apply the colour everywhere. Since this is what I didn't need, I just called mutate() on the Drawable (i.e like seekBar.getThumb().mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
I've seen this solution elsewhere but all it does (testing on a Gingerbread device) is turn the entire progress bar that one color, making it impossible see the actual progress
@NeilC.Obremski yes you're right. It might be ROM specific, or maybe version specific. I had to remove it altogether. Hopefully we will have this ported back to older versions of Android soon (via support lib).
C
Community

There are 3 ways to solve this question:

How to adjust the progressbar color declaratively How to adjust the progressbar color programmatically, but choose the color from various predetermined colors declared before compile-time How to adjust the progressbar color programmatically, and also create the color programatically.

In particular there is a lot of confusion around #2 and #3, as seen in comments to amfcosta's answer. That answer will yield unpredictable color results anytime you'd like to set the progressbar to anything except primary colors, as it only modifies the background color, and the actual progress bar "clip" area will still be a yellow overlay with reduced opacity. For example, using that method to set the background to dark purple will result in a progress bar "clip" color of some crazy pinkish color resulting from dark purple and yellow mixing via reduced alpha.

So anyhow, #1 is answered perfectly by Ryan and Štarke answers most of #3, but for those looking for a complete solution to #2 and #3:

How to adjust the progressbar color programmatically, but choose the color from a predetermined color declared in XML

res/drawable/my_progressbar.xml:

Create this file but change the colors in my_progress and my_secondsProgress:

(NOTE: This is just a copy of the actual XML file defining the default android SDK ProgressBar, but I've changed the IDs and Colors. The original is named 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>

In your 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)

How to adjust the progressbar color programmatically, and also create the color programatically

EDIT: I found the time to solve this properly. My former answer left this a bit ambiguous.

A ProgressBar is composed as 3 Drawables in a LayerDrawable.

Layer 1 is the background Layer 2 is the secondary progress color Layer 3 is the main progress bar color

In the example below I'll change the color of the main progress bar to cyan.

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

That example set it to a solid color. You may set it to a gradient color by replacing

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

with

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

Cheers.

-Lance


what's viewUtils in viewUtils.convertDpToPixel(5);
Hi @NikosHidalgo - You can see a nearly identical method here: stackoverflow.com/questions/12849366/…. The only difference is that I construct my ViewUtils with a reference to Context, so that I don't need to pass a Context when calling convertDpToPixel()
Thank you for your prompt reply, especially on an answer that was posted so long ago!
Haha, I really had to stretch my brain to remember :p
G
Gabriele Mariotti

With the Material Components Library you can use the LinearProgressIndicator with the app:indicatorColor attribute to change the color:

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

https://i.stack.imgur.com/flsca.png

Note: it requires at least the version 1.3.0-alpha04.

With the ProgressBar you can override the color using:

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

with:

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

https://i.stack.imgur.com/ij9tl.png


I recommend using this instead of the standard ProgressBar, as it allows you to change the track color as well while still having the material animation.
Í
Ícaro

If you are in API level 21 or above you can use these XML attributes:

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

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

Try to add a little explanation to your answer. Code only answers are discouraged.
I'd love to get an explanation behind the index 2 in getDrawable, but at least this was the only solution that worked for me, so thanks!
A
Alaa

simply add android:indeterminateTint="@color/colorPrimary" to your progressBar

Example:

<ProgressBar
    android:id="@+id/progressBar"
    style="?android:attr/progressBarStyle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:indeterminateTint="@color/colorPrimary"/>

in case of progressBarStyleHorizontal change android:progressTint="@color/colorPrimary"

Example:

 <ProgressBar
    android:id="@+id/progressBar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:progress="50"
    android:progressTint="@color/colorPrimary" />

S
Sazid

The simplest solution I found out is something like this:

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

Put the above in styles.xml file under res > values folder.

NOTE: If you use any other accent color, then the previous solutions should be good to go with.

API 21 or HIGHER


This is best solution. 100% related to asked question. very simple
Š
Štarke

For anyone looking for how to do it programmatically:

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

Setting ids to drawables is crucial, and takes care of preserving bounds and actual state of progress bar


P
Pier Betos

You guys are really giving me a headache. What you can do is make your layer-list drawable via xml first (meaning a background as the first layer, a drawable that represents secondary progress as the second layer, and another drawable that represents the primary progress as the last layer), then change the color on the code by doing the following:

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

This method will give you the best flexibility of having the measurement of your original drawable declared on the xml, WITH NO MODIFICATION ON ITS STRUCTURE AFTERWARDS, especially if you need to have the xml file screen folder specific, then just modifying ONLY THE COLOR via the code. No re-instantiating a new ShapeDrawable from scratch whatsoever.


M
Milan Hlinák

ProgressBar color can be changed as follows:

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

M
Md. Juyel Rana

Create a drawable resource what background you need, in my case I named it 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>

Then use this custom background like

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

Its works fine for me


A
Aminul Haque Aome

You can use custom drawable to make your Progressbar stylable. Create a drawable file

progress_user_badge.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 android:shape="rectangle">
            <corners android:radius="@dimen/_5sdp"/>
            <solid android:color="@color/your_default_color" />
        </shape>
    </item>

    <item android:id="@android:id/progress">
        <clip>
            <shape android:shape="rectangle">
                <corners android:radius="@dimen/_5sdp"/>
                <solid android:color="@color/your_exact_color" />
            </shape>
        </clip>
    </item>

</layer-list>

now use this drawable file in your widget

<ProgressBar
    android:id="@+id/badge_progress_bar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="@dimen/_200sdp"
    android:layout_height="@dimen/_7sdp"
    android:layout_gravity="center"
    android:layout_marginTop="@dimen/_15sdp"
    android:indeterminate="false"
    android:max="100"
    android:progress="70"
    android:progressDrawable="@drawable/progress_user_badge"/>

You can use the bellow line to change the progress color of Progressbar programmatically

badge_progress_bar.progressTintList = ColorStateList.valueOf(ContextCompat.getColor(this, R.color.your_color))

H
Hamza Mobi

Add android:indeterminateTint="@color/red" (your color) in your ProgressBar


S
Soumen Das

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

R
Rahul Kamble

If you want to set primary and secondary progress color to horizontal progress bar programmatically in android then use below snippet

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