In this tutorial, we’ll discuss and implement ProgressBar in our Android Application using Kotlin.
ProgressBar UI element is used to display the Progress on the app screen. We can use a ProgressBar to show the download/upload progress on the app screen.
There are two types of Progress Bar.
A ProgressDialog would hold a ProgressBar inside an Alert Dialog. ProgressDialog is now deprecated since it isn’t a good idea to show long progress in a dialog while blocking the screen.
Some of the important attributes of ProgressBar are:
android:indeterminate
- used to specify the boolean value indicating the type of the ProgressBarandroid:max
- The upper limit of the progressandroid:min
- The lower limit of the progressandroid:progress
- The steps by which the progress would be incremented.android:minWidth
and minHeight
- Used to define the dimensions of the ProgressBarandroid:progressBarTint
- The tint color of the progress completed of the ProgressBarandroid:progressBarBackgroundTint
- The tint color of the progress completed of the ProgressBarstyle
- Used to set the style of the ProgressBar. By default it is circular. We can set the style as @style/Widget.AppCompat.ProgressBar.Horizontal
for the Horizontal ProgressBarandroid:progressDrawable
- Is used to set a drawable for the progress.android:secondaryProgress
- Indicates the secondary progress value. This is used when we want to show the sub-downloads/subtasks progress.The default tint colors are set to the colorAccent
defined in the styles.xml
.
A basic circular indeterminate ProgressBar XML layout looks like this:
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="50dp"
android:minWidth="50dp" />
In the following section, we’ll implement various types of ProgressBars in our Android app using Kotlin.
The code for the activity_main.xml layout is as follows.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="50dp"
android:minWidth="50dp" />
<ProgressBar
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:minHeight="50dp"
android:minWidth="200dp" />
<TextView
android:id="@+id/textViewHorizontalProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0" />
<ProgressBar
android:id="@+id/progressBarHorizontal"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="false"
android:max="100"
android:minHeight="50dp"
android:minWidth="200dp"
android:progress="1"
android:progressBackgroundTint="@android:color/darker_gray"
android:progressTint="@color/colorPrimary" />
<Button
android:id="@+id/btnProgressBarHorizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="horizontalDeterminate"
android:text="DETERMINATE HORIZONTAL PROGRESS BAR" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ProgressBar
android:id="@+id/progressBarSecondary"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:minHeight="150dp"
android:padding="8dp"
android:minWidth="150dp"
android:progressDrawable="@drawable/progress_states" />
<TextView
android:id="@+id/textViewPrimary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="#000" />
<TextView
android:id="@+id/textViewSecondary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:layout_below="@+id/progressBarSecondary"
android:textColor="@color/colorPrimaryDark" />
</RelativeLayout>
<Button
android:id="@+id/btnProgressBarSecondary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="DETERMINATE SECONDARY PROGRESS BAR" />
</LinearLayout>
In the last progress bar, we’ve set a progress drawable on the horizontal ProgressBar. The drawable.xml file is progress_states.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 android:shape="oval">
<stroke
android:width="4dp"
android:color="@color/colorPrimary" />
<solid android:color="@android:color/white" />
</shape>
</item>
<item android:id="@android:id/secondaryProgress">
<clip
android:clipOrientation="vertical"
android:gravity="bottom">
<shape android:shape="oval">
<stroke
android:width="4dp"
android:color="@android:color/black" />
<solid android:color="@android:color/white" />
</shape>
</clip>
</item>
<item android:id="@android:id/progress">
<clip
android:clipOrientation="vertical"
android:gravity="bottom">
<shape android:shape="oval">
<stroke
android:width="4dp"
android:color="@color/colorAccent" />
<solid android:color="#F288F8" />
</shape>
</clip>
</item>
</layer-list>
In this drawable, we’ve created different states of the drawable. All are circular shaped and each layer would be displayed for the different states - idle, secondary progress, primary progress.
Let’s look at the MainActivity.kt Kotlin class code.
package net.androidly.androidlyprogressbar
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.view.View
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
var isStarted = false
var progressStatus = 0
var handler: Handler? = null
var secondaryHandler: Handler? = Handler()
var primaryProgressStatus = 0
var secondaryProgressStatus = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
handler = Handler(Handler.Callback {
if (isStarted) {
progressStatus++
}
progressBarHorizontal.progress = progressStatus
textViewHorizontalProgress.text = "${progressStatus}/${progressBarHorizontal.max}"
handler?.sendEmptyMessageDelayed(0, 100)
true
})
handler?.sendEmptyMessage(0)
btnProgressBarSecondary.setOnClickListener {
primaryProgressStatus = 0
secondaryProgressStatus = 0
Thread(Runnable {
while (primaryProgressStatus < 100) {
primaryProgressStatus += 1
try {
Thread.sleep(1000)
} catch (e: InterruptedException) {
e.printStackTrace()
}
startSecondaryProgress()
secondaryProgressStatus = 0
secondaryHandler?.post {
progressBarSecondary.progress = primaryProgressStatus
textViewPrimary.text = "Complete $primaryProgressStatus% of 100"
if (primaryProgressStatus == 100) {
textViewPrimary.text = "All tasks completed"
}
}
}
}).start()
}
}
fun startSecondaryProgress() {
Thread(Runnable {
while (secondaryProgressStatus < 100) {
secondaryProgressStatus += 1
try {
Thread.sleep(10)
} catch (e: InterruptedException) {
e.printStackTrace()
}
secondaryHandler?.post {
progressBarSecondary.setSecondaryProgress(secondaryProgressStatus)
textViewSecondary.setText("Current task progress\n$secondaryProgressStatus% of 100")
if (secondaryProgressStatus == 100) {
textViewSecondary.setText("Single task complete.")
}
}
}
}).start()
}
fun horizontalDeterminate(view: View) {
isStarted = !isStarted
}
}
The horizontalDeterminate
Kotlin function is triggered when the first button is clicked. It is used to start/stop Horizontal ProgressBar. A Handler is associated with a single thread. It is used to send messages to the Thread. The btnProgressBarSecondary
click triggers the second progress bar. We have created two handlers - one for the normal progress and second for the subtasks. In each of them, we are setting the thread to sleep. For the secondary thread, the sleep time is 1/100 of the primary progress thread. The progress value is displayed on the TextView. Output:
You can download the project from the following link: AndroidlyProgressBar
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
Thanks, had some problems with v7 compatibility, but then it worked fine. Thanks very much from Karcsi from Hungary
- karcsi halasz