How to create a Custom Progress Dialog in Android using Kotlin

Last updated on: May 27, 2023

In this tutorial, I’m going to show you how to make a Custom Progress Dialog for your Android app.

A Progress Dialog is a dialog with a progress indicator and text message.

Progress Dialog is useful while doing some task on your app that needs time to complete, like getting data from a server, because you don’t want to leave your users staring at their screens without letting them know that something is happening in the background.

Let’s get started!

In this example, we’re going to use CardView to give our Progress Dialog nice rounded corners. If you don’t want this, skip this step and use RelativeLayout instead.

Add the CardView dependency at the module-level of the build.gradle:

// ...

dependencies {
    // ...

    implementation "androidx.cardview:cardview:1.0.0"

    // ...
}Code language: Swift (swift)

Making the Custom Progress Dialog Layout

Go to res > layout and create the Custom Progress Dialog layout (progress_dialog_view.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"
        android:id="@+id/cp_bg_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#00000000"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

    <androidx.cardview.widget.CardView
            android:id="@+id/cp_cardview"
            android:layout_width="150dp"
            android:layout_height="150dp"
            app:cardBackgroundColor="#00000000"
            app:cardCornerRadius="16dp"
            app:cardElevation="0dp"
            app:cardMaxElevation="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">


        <androidx.constraintlayout.widget.ConstraintLayout
                android:id="@+id/cp_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="center"
                android:gravity="center">

            <ProgressBar
                    android:id="@+id/cp_pbar"
                    android:layout_width="match_parent"
                    android:layout_height="45dp"
                    android:layout_gravity="center"
                    android:layout_marginTop="8dp"
                    android:layout_marginBottom="8dp"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />

            <TextView
                    android:id="@+id/cp_title"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="8dp"
                    android:layout_marginEnd="8dp"
                    android:layout_marginBottom="15dp"
                    android:text=""
                    android:textColor="@android:color/white"
                    android:textStyle="bold"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent" />

        </androidx.constraintlayout.widget.ConstraintLayout>


    </androidx.cardview.widget.CardView>


</androidx.constraintlayout.widget.ConstraintLayout>Code language: HTML, XML (xml)

Creating the Custom Progress Dialog

Now, create the Kotlin class, named CustomProgressDialog.kt, and paste the following code inside:

class CustomProgressDialog(context: Context) {

private var dialog: CustomDialog
private var cpTitle: TextView
private var cpCardView: CardView
private var progressBar: ProgressBar

fun start(title: String = "") {
cpTitle.text = title
dialog.show()
}

fun stop() {
dialog.dismiss()
}

init {
val inflater = (context as Activity).layoutInflater
val view = inflater.inflate(R.layout.progress_dialog_view, null)

cpTitle = view.findViewById(R.id.cp_title)
cpCardView = view.findViewById(R.id.cp_cardview)
progressBar = view.findViewById(R.id.cp_pbar)

// Card Color
cpCardView.setCardBackgroundColor(Color.parseColor("#70000000"))

// Progress Bar Color
setColorFilter(
progressBar.indeterminateDrawable,
ResourcesCompat.getColor(context.resources, R.color.colorPrimary, null)
)

// Text Color
cpTitle.setTextColor(Color.WHITE)

// Custom Dialog initialization
dialog = CustomDialog(context)
dialog.setContentView(view)
}

private fun setColorFilter(drawable: Drawable, color: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
drawable.colorFilter = BlendModeColorFilter(color, BlendMode.SRC_ATOP)
} else {
@Suppress("DEPRECATION")
drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP)
}
}

class CustomDialog(context: Context) : Dialog(context, R.style.CustomDialogTheme) {
init {
// Set Semi-Transparent Color for Dialog Background
window?.decorView?.rootView?.setBackgroundResource(R.color.dialogBackground)
window?.decorView?.setOnApplyWindowInsetsListener { _, insets ->
insets.consumeSystemWindowInsets()
}
}
}
}

Now, go to res > values > styles.xml to set the theme for the Dialog:

<resources>

   <!-- Other Themes -->

    <style name="CustomDialogTheme">
        <item name="android:windowBackground">@android:color/transparent</item>
    </style>

</resources>Code language: HTML, XML (xml)

Using the Custom Progress Dialog

To use it, declare the class CustomProgressDialog at the beginning of your Activity:

class MainActivity : AppCompatActivity() {

    private val progressDialog by lazy { CustomProgressDialog(this) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    
        // ...    
    
    }
}Code language: Kotlin (kotlin)

… and show the Dialog with a title or not…

class MainActivity : AppCompatActivity() {
    
    private val progressDialog by lazy { CustomProgressDialog(this) }

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

        val startButton = findViewById<Button>(R.id.start_btn)
        startButton.setOnClickListener {

            // Show progress dialog with title
            progressDialog.start("Please Wait...")

            // Show progress dialog without title
            progressDialog.start()

            // ...

        }
    }
}Code language: Kotlin (kotlin)

… and dismiss it using:

class MainActivity : AppCompatActivity() {

    private val progressDialog = CustomProgressDialog()

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

        val startButton = findViewById<Button>(R.id.start_btn)
        startButton.setOnClickListener {
            
            // ...

            Handler(Looper.getMainLooper()).postDelayed({
                // Dismiss progress bar after 4 seconds
                progressDialog.stop()
            }, 4000)
        }
    }
}Code language: Kotlin (kotlin)
You can find the final project here

If you have any questionsplease feel free to leave a comment below

Subscribe
Notify of
guest
16 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments