Android
ProgressBar
UI Design
Android Development
Customization

How to change ProgressBar's progress indicator color in Android

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Android's default ProgressBar uses the theme's accent color for the progress indicator. To customize this color, you can use XML theme attributes, a custom drawable, or change it programmatically at runtime. The best approach depends on whether you need a static color or one that changes dynamically based on state. All three methods work for both determinate and indeterminate progress bars.

XML Theme Attribute (Simplest)

The quickest way to change the progress color is via the android:progressTint attribute (API 21+):

xml
1<ProgressBar
2    android:id="@+id/progressBar"
3    style="?android:attr/progressBarStyleHorizontal"
4    android:layout_width="match_parent"
5    android:layout_height="wrap_content"
6    android:max="100"
7    android:progress="50"
8    android:progressTint="#FF4081"
9    android:progressBackgroundTint="#E0E0E0" />

For an indeterminate spinner, use android:indeterminateTint:

xml
1<ProgressBar
2    android:id="@+id/spinner"
3    android:layout_width="wrap_content"
4    android:layout_height="wrap_content"
5    android:indeterminateTint="#FF4081" />

Custom Drawable (Full Control)

Create a drawable XML file at res/drawable/custom_progress.xml for complete control over colors, gradients, and shapes:

xml
1<?xml version="1.0" encoding="utf-8"?>
2<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
3    <!-- Background -->
4    <item android:id="@android:id/background">
5        <shape>
6            <corners android:radius="4dp" />
7            <solid android:color="#E0E0E0" />
8        </shape>
9    </item>
10
11    <!-- Secondary progress (e.g., buffer) -->
12    <item android:id="@android:id/secondaryProgress">
13        <clip>
14            <shape>
15                <corners android:radius="4dp" />
16                <solid android:color="#80FF4081" />
17            </shape>
18        </clip>
19    </item>
20
21    <!-- Primary progress -->
22    <item android:id="@android:id/progress">
23        <clip>
24            <shape>
25                <corners android:radius="4dp" />
26                <solid android:color="#FF4081" />
27            </shape>
28        </clip>
29    </item>
30</layer-list>

Apply it to the ProgressBar:

xml
1<ProgressBar
2    style="?android:attr/progressBarStyleHorizontal"
3    android:layout_width="match_parent"
4    android:layout_height="8dp"
5    android:progressDrawable="@drawable/custom_progress" />

The @android:id/background, @android:id/secondaryProgress, and @android:id/progress layer IDs are required for Android to map each layer correctly.

Programmatic Approach

Change the color at runtime using setProgressTintList (API 21+):

kotlin
1import android.content.res.ColorStateList
2import android.graphics.Color
3
4val progressBar = findViewById<ProgressBar>(R.id.progressBar)
5
6// Set progress color
7progressBar.progressTintList = ColorStateList.valueOf(Color.parseColor("#FF4081"))
8
9// Set background color
10progressBar.progressBackgroundTintList = ColorStateList.valueOf(Color.parseColor("#E0E0E0"))
11
12// For indeterminate spinner
13progressBar.indeterminateTintList = ColorStateList.valueOf(Color.RED)

For API levels below 21, use DrawableCompat:

kotlin
1import androidx.core.graphics.drawable.DrawableCompat
2
3val drawable = progressBar.progressDrawable.mutate()
4DrawableCompat.setTint(drawable, Color.parseColor("#FF4081"))
5progressBar.progressDrawable = drawable

The mutate() call clones the drawable so that color changes do not affect other views sharing the same drawable resource.

Changing Color Based on Progress Value

A common pattern is changing color as progress increases (green to red):

kotlin
1progressBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
2    override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
3        val color = when {
4            progress < 30 -> Color.RED
5            progress < 70 -> Color.parseColor("#FFA500") // Orange
6            else -> Color.GREEN
7        }
8        seekBar.progressTintList = ColorStateList.valueOf(color)
9    }
10    override fun onStartTrackingTouch(seekBar: SeekBar) {}
11    override fun onStopTrackingTouch(seekBar: SeekBar) {}
12})

Using Theme Overlay

Apply a color via your app theme to affect all progress bars:

xml
1<!-- res/values/themes.xml -->
2<style name="AppTheme" parent="Theme.MaterialComponents.Light">
3    <item name="colorAccent">#FF4081</item>
4    <!-- Or for Material 3 -->
5    <item name="colorPrimary">#FF4081</item>
6</style>

Override for a specific ProgressBar using android:theme:

xml
1<ProgressBar
2    android:layout_width="wrap_content"
3    android:layout_height="wrap_content"
4    android:theme="@style/PinkProgress" />
5
6<style name="PinkProgress" parent="">
7    <item name="colorAccent">#FF4081</item>
8</style>

Common Pitfalls

  • Forgetting mutate() on shared drawables: Without mutate(), calling setTint or setColorFilter on a progress drawable changes the color for every view using that drawable. Always call mutate() first when modifying drawables programmatically.
  • Using progressTint below API 21: The android:progressTint XML attribute and setProgressTintList() require API 21+. On older devices, use DrawableCompat.setTint() from the AndroidX library or a custom drawable XML.
  • Missing layer IDs in custom drawables: If you omit @android:id/progress or @android:id/background from your layer-list, the ProgressBar cannot identify which layer to clip and the bar appears empty or fully filled.
  • Indeterminate vs determinate tint: android:progressTint only affects the determinate bar. For the spinning indeterminate animation, you must use android:indeterminateTint instead.
  • RTL layout issues: Custom progress drawables using ClipDrawable default to left-to-right clipping. For RTL support, set android:autoMirrored="true" on the drawable or use android:layoutDirection on the ProgressBar.

Summary

  • Use android:progressTint for a quick color change on API 21+
  • Create a custom layer-list drawable for full control over background, secondary progress, and primary progress colors
  • Use setProgressTintList() or DrawableCompat.setTint() for runtime color changes
  • Always call mutate() before modifying shared drawables to avoid affecting other views
  • Use android:indeterminateTint for spinner-style progress bars
  • Apply android:theme with colorAccent to restyle individual progress bars without a custom drawable

Course illustration
Course illustration

All Rights Reserved.