Android Kotlin: How to change progress bar color programmatically

Introduction

This code demonstrates two methods for programmatically changing the color of a progress bar in an Android application written in Kotlin. The code also includes a button click listener that initiates a simulated task that updates the progress bar value and text view.

Explanation

  1. MainActivity.kt

    • The progressStatus variable is an integer that keeps track of the progress bar's fill level.
    • The handler variable is a Handler instance used to update the UI elements from a background thread.
  2. onCreate() method:

    • This method inflates the activity_main.xml layout and retrieves references to the widgets:

      • Button (button)
      • TextView (textView)
      • Three ProgressBars (progressBar, progressBar2, progressBar3)
    • Setting progress bar color (tint) programmatically:

      • The code sets the progressTintList and progressBackgroundTintList properties of progressBar2 to a ColorStateList with a blue color. This approach works for all API levels.
    • Another way to change progress bar color:

      • The code checks the Android version using Build.VERSION.SDK_INT.
      • If the API level is 29 (Android 10) or higher, it uses a BlendModeColorFilter with the source-in blend mode to set the progress bar's color filter to red.
      • For lower API levels, it uses a ColorFilter with the source-in PorterDuff mode to achieve the same effect.
    • Button click listener:

      • When the button is clicked, a new thread is started.
      • Inside the thread, a loop iterates until progressStatus reaches 100.
      • Within the loop:
        • The progressStatus is incremented by 1.
        • The thread sleeps for 100 milliseconds to simulate some work being done.
      • The handler.post() method is used to update the UI elements from the background thread:
        • The progress of all three progress bars (progressBar, progressBar2, progressBar3) is set to the current progressStatus.
        • The text view's text is updated to display the current progressStatus.
  3. activity_main.xml

    • This file defines the layout of the activity, including:
      • A TextView to display the progress status
      • Three ProgressBars
      • A Button to start the simulated task

Summary

This code provides a comprehensive example of how to programmatically change the color of a progress bar in Android using Kotlin. It covers two different approaches and also demonstrates how to update the progress bar value and text view from a background thread.


MainActivity.kt

package com.cfsuman.kotlintutorials

import android.app.Activity
import android.content.res.ColorStateList
import android.graphics.BlendMode
import android.graphics.BlendModeColorFilter
import android.graphics.Color
import android.graphics.PorterDuff
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.widget.Button
import android.widget.ProgressBar
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout


class MainActivity : Activity() {
    var progressStatus = 0
    var handler = Handler(Looper.getMainLooper())

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Get the widgets reference from XML layout
        val button = findViewById<Button>(R.id.button)
        val textView = findViewById<TextView>(R.id.textView)
        val progressBar = findViewById<ProgressBar>(R.id.progressBar)
        val progressBar2 = findViewById<ProgressBar>(R.id.progressBar2)
        val progressBar3 = findViewById<ProgressBar>(R.id.progressBar3)


        // set progressbar color (tint) programmatically
        progressBar2.progressTintList = ColorStateList.valueOf(Color.BLUE)
        progressBar2.progressBackgroundTintList = ColorStateList
            .valueOf(Color.BLUE)


        // another way to change progress bar color
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            progressBar3.progressDrawable.colorFilter =
                BlendModeColorFilter(Color.RED, BlendMode.SRC_IN)
        }else {
            progressBar3.progressDrawable
                .setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN)
        }


        // set button click listener
        button.setOnClickListener {
            Thread {
                while (progressStatus < 100) {
                    // update progress status
                    progressStatus += 1

                    // sleep the thread for 100 milliseconds
                    Thread.sleep(100)

                    // update the progress bar
                    handler.post {
                        progressBar.progress = progressStatus
                        progressBar2.progress = progressStatus
                        progressBar3.progress = progressStatus
                        textView.text = "$progressStatus"
                    }
                }
            }.start()
        }
    }
}
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/rootLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="24dp"
    android:background="#DCDCDC">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:padding="12dp"
        android:fontFamily="sans-serif"
        android:textSize="20sp"
        android:textStyle="bold"
        tools:text="TextView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="12dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

    <ProgressBar
        android:id="@+id/progressBar2"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="12dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/progressBar" />

    <ProgressBar
        android:id="@+id/progressBar3"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="12dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/progressBar2" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="Start Task"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/progressBar3" />

</androidx.constraintlayout.widget.ConstraintLayout>
More android kotlin tutorials