Android
Progress Bar
Customization
UI Design
Android Development

How to change progress bar's progress 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

Changing a progress bar's color in Android depends on whether the bar is determinate or indeterminate and on how much visual control you need. For simple cases, tinting is enough. For custom track, corners, and secondary-progress styling, a drawable is the better approach.

The Easiest Modern Approach

For many modern apps, tint properties are enough:

xml
1<ProgressBar
2    android:id="@+id/progressBar"
3    android:layout_width="match_parent"
4    android:layout_height="wrap_content"
5    android:progressTint="@color/teal_700"
6    android:progressBackgroundTint="@color/gray"
7    android:indeterminateTint="@color/teal_700" />

progressTint changes the filled portion of a determinate bar. indeterminateTint changes the spinning or animated indicator. This is the simplest answer when you only need color and not a custom shape.

Custom Drawable for More Control

If you want rounded corners or a separate secondary-progress color, define a drawable:

xml
1<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
2    <item android:id="@android:id/background">
3        <shape>
4            <corners android:radius="4dp" />
5            <solid android:color="#D0D0D0" />
6        </shape>
7    </item>
8    <item android:id="@android:id/progress">
9        <clip>
10            <shape>
11                <corners android:radius="4dp" />
12                <solid android:color="#009688" />
13            </shape>
14        </clip>
15    </item>
16</layer-list>

Then point the ProgressBar at it:

xml
1<ProgressBar
2    android:layout_width="match_parent"
3    android:layout_height="wrap_content"
4    android:progressDrawable="@drawable/custom_progress" />

This gives you much more control than a simple tint.

Changing Color in Code

Sometimes the color depends on runtime state:

kotlin
val progressBar = findViewById<ProgressBar>(R.id.progressBar)
progressBar.progressTintList = ColorStateList.valueOf(Color.RED)
progressBar.indeterminateTintList = ColorStateList.valueOf(Color.BLUE)

That is useful when progress color reflects status such as warning, success, or error.

Determinate Versus Indeterminate

A common source of confusion is that determinate and indeterminate progress bars do not use exactly the same drawable behavior. If the bar is indeterminate, changing progressDrawable alone may not affect the animated indicator. In that case, indeterminateTint or a dedicated indeterminate drawable is the right tool.

Theme Consistency

If progress bars appear across the app, consider defining the colors in the theme or style system instead of hardcoding them repeatedly. That keeps dark mode and branding changes much easier to manage.

For Material-based apps, centralizing these values also reduces drift between progress bars, sliders, and other indicators that are supposed to share a visual language. UI polish problems often come from a handful of widgets being tinted ad hoc while the rest of the app follows theme tokens.

Compatibility Notes

Old code samples often use setColorFilter with PorterDuff.Mode.SRC_IN. That still appears in legacy code, but tint APIs and tint lists are usually clearer for modern Android development. If you support older platform levels, test both XML and runtime tint behavior carefully, because reused drawable instances can sometimes inherit color unexpectedly when they are not mutated properly.

Another subtle issue is style inheritance. A progress bar may look wrong not because your drawable is broken, but because a theme or widget style is applying an unexpected tint on top. When debugging, inspect both the view XML and the active app theme.

That extra check often explains why the same drawable behaves differently across screens.

It is a very common theming gotcha.

Common Pitfalls

  • Changing progressDrawable and expecting it to affect an indeterminate spinner.
  • Forgetting mutate() or tint-list behavior when reusing drawables in code.
  • Hardcoding colors instead of using resources and theme values.
  • Styling the progress color but leaving the track color unreadable.
  • Using a custom drawable when a simple tint would have been enough.

Summary

  • Use progressTint and indeterminateTint for the simplest color changes.
  • Use a custom progressDrawable when you need shape and track control.
  • Determinate and indeterminate bars are styled differently.
  • Runtime color changes are easy through tint lists in code.
  • Prefer theme resources over repeated hardcoded colors.

Course illustration
Course illustration

All Rights Reserved.