Tuesday, June 2, 2020

android kotlin - Horizontal ProgressBar programmatically

MainActivity.kt

package com.cfsuman.kotlintutorials

import android.app.Activity
import android.content.Context
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.TypedValue
import android.view.View
import android.widget.Button
import android.widget.ProgressBar
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams
import androidx.constraintlayout.widget.ConstraintSet
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 references from XML layout
        val rootLayout = findViewById<ConstraintLayout>(R.id.rootLayout)
        val button = findViewById<Button>(R.id.button)
        val textView = findViewById<TextView>(R.id.textView)


        // Create a horizontal progress bar programmatically
        val progressBar = ProgressBar(
            this,
            null,
            android.R.attr.progressBarStyleHorizontal
        )

        // Generate a view id for the progress bar
        progressBar.id = View.generateViewId()

        // Progress bar width and height
        val params = LayoutParams(
            LayoutParams.MATCH_PARENT,
            LayoutParams.WRAP_CONTENT
        )
        progressBar.layoutParams = params

        // Add the progress bar to constraint layout
        rootLayout.addView(progressBar)

        // Initialize a new constraint set
        val constraintSet = ConstraintSet()
        constraintSet.clone(rootLayout)

        // Put the progress bar bottom of text view
        constraintSet.connect(
            // Connect progress bar top to text view's bottom
            progressBar.id,
            ConstraintSet.TOP,
            R.id.textView,
            ConstraintSet.BOTTOM,
            24.toDp(this) // Margin
        )

        // Start constraint with margin
        constraintSet.connect(
            progressBar.id,
            ConstraintSet.START,
            R.id.rootLayout,
            ConstraintSet.START,
            16.toDp(this) // Margin
        )

        // End constraint with margin
        constraintSet.connect(
            progressBar.id,
            ConstraintSet.END,
            R.id.rootLayout,
            ConstraintSet.END,
            16.toDp(this)
        )

        // Finally, apply the constraint to constraint layout
        constraintSet.applyTo(rootLayout)


        // Set the button click listener
        button.setOnClickListener {
            button.isEnabled = false

            // Set up progress bar on initial stage
            progressBar.progress = 0
            progressStatus = 0

            // Generate random number of files to download
            val filesToDownload= Random.nextInt(10,200)

            // Set up max value for progress bar
            progressBar.max = filesToDownload

            Thread {
                while (progressStatus < filesToDownload) {
                    // Update progress status
                    progressStatus += 1

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

                    // Update the progress bar
                    handler.post {
                        progressBar.progress = progressStatus

                        // 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
                        }
                    }
                }
            }.start()
        }
    }
}



// Extension method to convert values to dp
fun Int.toDp(context: Context):Int = TypedValue.applyDimension(
    TypedValue.COMPLEX_UNIT_DIP,
    this.toFloat(),
    context.resources.displayMetrics
).toInt()
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">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start Task"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

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

</androidx.constraintlayout.widget.ConstraintLayout>