This code demonstrates how to create an indeterminate progress bar in an Android app written in Kotlin. An indeterminate progress bar indicates an ongoing operation without a specific duration. It's useful for scenarios where the exact time to complete a task is unknown.
Breakdown of the code:
The code consists of two parts:
- MainActivity.kt: This file handles the logic behind the progress bar functionality.
- activity_main.xml: This file defines the user interface layout for the app.
MainActivity.kt:
- It defines variables for tracking progress (
progressStatus
) and a handler (handler
) for updating the UI thread. - In the
onCreate
method, it references the UI elements (button, text view, progress bar) from the layout. - The button click listener performs the following actions:
- Disables the button to prevent multiple clicks.
- Uses
TransitionManager
for a smooth animation when showing the progress bar. - Sets the progress bar properties: initial progress, max value, and visibility.
- Starts a new thread to simulate a download process.
- The thread continuously updates the
progressStatus
and sleeps for a short duration to mimic download time. - Inside the thread, a
handler.post
block updates the UI thread:- Calculates the download percentage.
- Updates the text view with download progress.
- Once the download is complete, it re-enables the button and hides the progress bar with another animation.
activity_main.xml:
- This file defines the layout using ConstraintLayout.
- It includes a text view displaying progress information, a progress bar with specific attributes, and a button to trigger the download task.
Summary
This code provides a basic example of using an indeterminate progress bar in Kotlin. It demonstrates how to simulate a download process with a progress indicator, update the UI thread from a background thread, and manage button interaction during the download. You can adapt this code for various scenarios where you need to visually represent an ongoing operation in your Android app.
MainActivity.kt
package com.cfsuman.kotlintutorials
import android.app.Activity
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.View
import android.widget.Button
import android.widget.ProgressBar
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.transition.TransitionManager
import kotlin.random.Random
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 rootLayout = findViewById<ConstraintLayout>(R.id.rootLayout)
val button = findViewById<Button>(R.id.button)
val textView = findViewById<TextView>(R.id.textView)
val progressBar = findViewById<ProgressBar>(R.id.progressBar)
// Button click listener
button.setOnClickListener {
button.isEnabled = false
TransitionManager.beginDelayedTransition(rootLayout)
progressBar.visibility = View.VISIBLE
// Set up progress bar on initial stage
progressBar.progress = 0
progressStatus = 0
// Generate random number of files to download
val filesToDownload= Random.nextInt(10,50)
// Set up max value for progress bar
progressBar.max = filesToDownload
Thread {
while (progressStatus < filesToDownload) {
// Update progress status
progressStatus += 1
// Sleep the thread for 200 milliseconds
Thread.sleep(200)
// Update the progress bar
handler.post {
// Calculate the percentage
var percentage = ((progressStatus.toDouble()
/ filesToDownload) * 100).toInt()
// Update the text view
textView.text = "Downloaded $progressStatus of " +
"$filesToDownload files ($percentage%)"
if (progressStatus == filesToDownload) {
button.isEnabled = true
TransitionManager
.beginDelayedTransition(rootLayout)
progressBar.visibility = View.GONE
}
}
}
}.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:visibility="gone"
android:indeterminate="true"
android:indeterminateBehavior="cycle"
android:indeterminateOnly="true"
android:layout_marginTop="12dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<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/progressBar" />
</androidx.constraintlayout.widget.ConstraintLayout>