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.


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.


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>

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.


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.


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"

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


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"

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


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

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


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.


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

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


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
    }

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


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));
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.