Jak zmienić kolor wskaźnika postępu ProgressBar w systemie Android

178

Ustawiłem poziomo ProgressBar.

Chciałbym zmienić kolor postępu na żółty.

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

Problem w tym, że kolor postępu jest różny na różnych urządzeniach. Więc chcę, żeby poprawił kolor postępu.

Nishant Shah
źródło
powyższe odpowiedzi zmieniają kolor całego tła i jest niejednoznaczne, że zmienia wysokość paska postępu na bardzo maksymalną, której nie można zmienić w xml. Lepszy sposób na zmianę stanu paska postępu tylko, że ukończone jest 20% koloru czerwonego, 50% koloru żółtego 70% i powyżej koloru zielonego. możesz to zrobić programowo w java. podziel się swoją odpowiedzią, jeśli masz inne rozwiązanie.
Mubashar

Odpowiedzi:

365

Skopiowałem to z jednej z moich aplikacji, więc jest kilka dodatkowych atrybutów, ale powinienem dać ci pomysł. To pochodzi z układu z paskiem postępu:

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

Następnie utwórz nowy element rysunkowy z czymś podobnym do następującego (w tym przypadku 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>

W razie potrzeby możesz zmienić kolory, co da ci zielony pasek postępu.

Ryan
źródło
Usuwam też tego androida: indeterminate = "false"
Nishant Shah
2
Proszę pomóż mi. Próbuję utworzyć greenprogress.xml, kopiując twój kod, ale Android Studio 0.4.6 zaznacza <layer-list> jako i błąd "Lista elementów musi być zadeklarowana" co mam zrobić?
UmAnusorn,
1
Czy można dynamicznie zmieniać kolor?
async
czy można zmienić kolor w zależności od aktualnej wartości postępu zdefiniowanej na aktualnym pasku?
Jonathan
@Ryan Dobrze byłoby wyjaśnić, co android:id="@android:id/progress", android:id="@android:id/background"i android:id="@android:id/secondaryProgress"stanąć na.
RustamG
103

Prostsze rozwiązanie:

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>
Nitin Saxena
źródło
1
here @ color / disabled to niestandardowy kolor
Nitin Saxena
2
Lub <solid android: color = "@ android: color / black" />, a nawet <solid android: color = "# ff33b5e5" />
superarts.org
2
To wystarczy android: indeterminateTint = "@ color / white" dla dźwigni API 21 i nowszych
Ghanshyam Nayma
53

Po prostu stwórz styl w values/styles.xml.

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

Następnie ustaw ten styl jako swój ProgressBarmotyw.

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

i nie ma znaczenia, czy pasek postępu jest poziomy czy okrągły. To wszystko.

Ali Zeynali
źródło
1
Wow, najprostsze rozwiązanie działa dla mnie. Zastanawiałem się, dlaczego ta odpowiedź ma tyle głosów.
Pavel Shorokhov
38

Jeśli chcesz zmienić tylko kolor paska postępu, możesz po prostu użyć filtru kolorów w metodzie onCreate () swojego działania:

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

Pomysł stąd .

Musisz to zrobić tylko dla wersji przed Lollipopem. W Lollipopie możesz użyć atrybutu stylu colorAccent.

amfcosta
źródło
Za SeekBarto samo, po prostu dodaj do API 16: seekBar.getThumb().setColorFilter(color, PorterDuff.Mode.SRC_IN);. To zmieni kolor tego okrągłego kciuka.
Sufian
1
Wezwanie setColorFilter()do rysowania bezpośrednio spowoduje zastosowanie koloru wszędzie. Ponieważ jest to czego nie trzeba, po prostu nazywa mutate()się na Drawable(czyli jakseekBar.getThumb().mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
Sufian
3
Widziałem to rozwiązanie gdzie indziej, ale wszystko, co robi (testowanie na urządzeniu Gingerbread) to obrócenie całego paska postępu o jeden kolor, uniemożliwiając zobaczenie rzeczywistego postępu
Neil C. Obremski
@ NeilC.Obremski tak, masz rację. Może to być specyficzne dla ROM lub specyficzne dla wersji. Musiałem go całkowicie usunąć. Mamy nadzieję, że wkrótce przywrócimy to do starszych wersji Androida (przez support lib).
Sufian
25

dla poziomu API 21 lub wyższego po prostu użyj

android:progressBackgroundTint="@color/yourBackgroundColor"
android:progressTint="@color/yourColor"
Mohammad Mousavi
źródło
6

Istnieją 3 sposoby rozwiązania tego pytania:

  1. Jak ustawić deklaratywnie kolor paska postępu
  2. Jak programowo dostosować kolor paska postępu, ale wybrać kolor z różnych z góry określonych kolorów zadeklarowanych przed kompilacją
  3. Jak programowo dostosować kolor paska postępu, a także programowo utworzyć kolor.

W szczególności istnieje wiele nieporozumień wokół # 2 i # 3, jak widać w komentarzach do odpowiedzi amfcosta. Ta odpowiedź przyniesie nieprzewidywalne wyniki kolorów za każdym razem, gdy zechcesz ustawić pasek postępu na cokolwiek z wyjątkiem kolorów podstawowych, ponieważ modyfikuje on tylko kolor tła, a rzeczywisty obszar „przycinania” paska postępu nadal będzie żółtą nakładką ze zmniejszonym kryciem. Na przykład, użycie tej metody do ustawienia ciemnofioletowego tła spowoduje, że pasek postępu będzie miał kolor „klipu” o szalonym różowawym kolorze, będący wynikiem mieszania ciemnego fioletu i żółtego poprzez zredukowane alfa.

Tak czy owak, odpowiedź nr 1 doskonale odpowiada Ryan i Štarke, większość odpowiedzi nr 3, ale dla tych, którzy szukają kompletnego rozwiązania nr 2 i 3:


Jak programowo dostosować kolor paska postępu, ale wybrać kolor z wcześniej określonego koloru zadeklarowanego w XML

res / drawable / my_progressbar.xml :

Utwórz ten plik, ale zmień kolory w my_progress i my_secondsProgress:

(UWAGA: to jest tylko kopia rzeczywistego pliku XML definiującego domyślny ProgressBar Android SDK, ale zmieniłem identyfikatory i kolory. Oryginał nosi nazwę 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>

W Twojej Javie :

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)

Jak programowo dostosować kolor paska postępu, a także programowo utworzyć kolor

EDYCJA: znalazłem czas na poprawne rozwiązanie tego problemu. Moja poprzednia odpowiedź pozostawiła to nieco niejednoznaczne.

ProgressBar składa się z 3 Drawables w LayerDrawable.

  1. Warstwa 1 to tło
  2. Warstwa 2 to dodatkowy kolor postępu
  3. Warstwa 3 to główny kolor paska postępu

W poniższym przykładzie zmienię kolor głównego paska postępu na cyjan.

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

Ten przykład ustawił go na jednolity kolor. Możesz ustawić go na kolor gradientu, zastępując

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

z

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

Twoje zdrowie.

-Lanca

lance.dolan
źródło
co jest viewUtils w viewUtils.convertDpToPixel (5);
Nikos Hidalgo,
1
Cześć @NikosHidalgo - Tutaj możesz zobaczyć prawie identyczną metodę: stackoverflow.com/questions/12849366/… . Jedyna różnica polega na tym, że konstruuję moje ViewUtilsz odniesieniem do Context, dzięki czemu nie muszę podawać a Contextpodczas dzwonieniaconvertDpToPixel()
lance.dolan
Dziękuję za szybką odpowiedź, szczególnie w przypadku odpowiedzi, która została opublikowana tak dawno temu!
Nikos Hidalgo,
Haha, naprawdę musiałem
wyciągnąć
4

Jeśli jesteś na poziomie API 21 lub wyższym, możesz użyć następujących atrybutów XML:

<!-- For indeterminate progress bar -->
android:indeterminateTint="@color/white"
<!-- For normal progress bar -->
android:progressTint="@color/white"
Ghanshyam Nayma
źródło
3

Najprostsze rozwiązanie, które znalazłem, jest takie:

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

Umieść powyższe w styles.xmlpliku w res > valuesfolderze.

UWAGA: Jeśli użyjesz innego koloru akcentującego, poprzednie rozwiązania powinny być dobre.

API 21 lub WYŻSZY

Sazid
źródło
To najlepsze rozwiązanie. 100% związane z zadanym pytaniem. bardzo proste
Pir Fahim Shah
3
final LayerDrawable layers = (LayerDrawable) progressBar.getProgressDrawable();
layers.getDrawable(2).setColorFilter(color,PorterDuff.Mode.SRC_IN);
user3135773
źródło
1
Spróbuj dodać trochę wyjaśnienia do swojej odpowiedzi. Tylko kod odpowiedzi są odradzane.
Alexei
Bardzo chciałbym uzyskać wyjaśnienie dotyczące indeksu 2 w getDrawable, ale przynajmniej było to jedyne rozwiązanie, które zadziałało w moim przypadku, więc dzięki!
Nikos Hidalgo,
2

Dla każdego, kto szuka, jak to zrobić programowo:

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

Ustawienie identyfikatorów na drawables jest kluczowe i dba o zachowanie granic i aktualnego stanu paska postępu

Štarke
źródło
1

Naprawdę przyprawiacie mnie o ból głowy. To, co możesz zrobić, to najpierw stworzyć listę warstw do rysowania za pomocą XML (co oznacza tło jako pierwszą warstwę, do rysowania, które reprezentuje postęp drugorzędny jako druga warstwa, a drugą do rysowania, która reprezentuje podstawowy postęp jako ostatnia warstwa), a następnie zmień kolor na kodzie, wykonując następujące czynności:

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

Ta metoda zapewnia najlepszą elastyczność wynikającą z zadeklarowania pomiaru oryginalnego elementu do rysowania w formacie xml, BEZ ZMIAN W JEGO STRUKTURZE W PÓŹNIEJSZYM POSTĘPOWANIU, szczególnie jeśli potrzebujesz określić folder ekranu pliku xml, a następnie zmodyfikować TYLKO KOLOR za pomocą kod. Żadnego ponownego tworzenia instancji nowego ShapeDrawable od zera.

Pier Betos
źródło
1

Kolor paska postępu można zmienić w następujący sposób:

/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);
}
Milan Hlinák
źródło
1

Utwórz zasób do rysowania, jakiego tła potrzebujesz, w moim przypadku nazwałem go 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>

Następnie użyj tego niestandardowego tła, takiego jak

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

U mnie działa dobrze

Md Juyel Rana
źródło
0

W 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
źródło
0

W Bibliotece komponentów materiałów możesz użyć atrybutu ProgressIndicatorz app:indicatorColoratrybutem, aby zmienić kolor:

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

wprowadź opis obrazu tutaj

Uwaga : wymaga co najmniej wersji 1.3.0-alpha01.

Za pomocą ProgressBarmożesz nadpisać kolor używając:

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

z:

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

wprowadź opis obrazu tutaj

Gabriele Mariotti
źródło
0

Jeśli chcesz programowo ustawić podstawowy i dodatkowy kolor postępu na poziomy pasek postępu w systemie Android, użyj poniższego fragmentu kodu

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));
Rahul Kamble
źródło