Android ProgressBar Leitfaden in Kotlin

In diesem Tutorial besprechen und implementieren wir ProgressBar in unserer Android-Anwendung mit Kotlin.

Was ist eine Android ProgressBar?

Das UI-Element ProgressBar wird verwendet, um den Fortschritt auf dem App-Bildschirm anzuzeigen. Wir können eine ProgressBar verwenden, um den Download-/Upload-Fortschritt auf dem App-Bildschirm anzuzeigen.

Android ProgressBar-Typen

Es gibt zwei Arten von ProgressBar.

  • Determinate ProgressBar – Diese wird verwendet, wenn Sie den abgeschlossenen Fortschritt verfolgen und anzeigen können.
  • Indeterminate ProgressBar – Diese läuft unendlich, bis sie gestoppt wird.

Ein ProgressDialog enthält eine ProgressBar innerhalb eines Alert Dialogs. ProgressDialog ist jetzt veraltet, da es keine gute Idee ist, einen langen Fortschritt in einem Dialog anzuzeigen, während der Bildschirm blockiert wird.

ProgressBar-Attribute

Einige der wichtigsten Attribute einer ProgressBar sind:

  • android:indeterminate – wird verwendet, um den booleschen Wert anzugeben, der den Typ der ProgressBar angibt
  • android:max – Das obere Limit des Fortschritts
  • android:min – Das untere Limit des Fortschritts
  • android:progress – Die Schritte, um die der Fortschritt erhöht wird.
  • android:minWidth und minHeight – Verwendet, um die Abmessungen der ProgressBar zu definieren
  • android:progressBarTint – Die Tönungsfarbe des abgeschlossenen Fortschritts der ProgressBar
  • android:progressBarBackgroundTint – Die Tönungsfarbe des Hintergrunds der ProgressBar
  • style – Wird verwendet, um den Stil der ProgressBar festzulegen. Standardmäßig ist sie rund. Wir können den Stil als @style/Widget.AppCompat.ProgressBar.Horizontal für die horizontale ProgressBar festlegen
  • android:progressDrawable – Wird verwendet, um ein Drawable für den Fortschritt festzulegen.
  • android:secondaryProgress – Zeigt den sekundären Fortschrittswert an. Dies wird verwendet, wenn wir den Fortschritt von Unterdownloads/Unteraufgaben anzeigen möchten.

Die Standard-Tönungsfarben sind auf die in der styles.xml definierte Farbe colorAccent eingestellt.

Android ProgressBar XML-Layout

Ein grundlegendes XML-Layout einer kreisförmigen indeterminierten ProgressBar sieht folgendermaßen aus:

<ProgressBar
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:minHeight="50dp"
    android:minWidth="50dp" />

Im folgenden Abschnitt implementieren wir verschiedene Arten von ProgressBars in unserer Android-App mit Kotlin.

1. ProgressBar: XML-Layout-Code

Der Code für das activity_main.xml-Layout sieht folgendermaßen aus:

<?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="DETERMINIERTE HORIZONTALE FORTSCHRITTSANZEIGE" />

    <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="DETERMINIERTE SEKUNDÄRE FORTSCHRITTSANZEIGE" />

</LinearLayout>

In der letzten Android ProgressBar haben wir ein Fortschritts-Drawable auf die horizontale ProgressBar gesetzt. Die drawable.xml-Datei ist 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 diesem Drawable haben wir verschiedene Zustände des Drawables erstellt. Alle sind kreisförmig und jede Ebene wird für die verschiedenen Zustände angezeigt – Leerlauf, sekundärer Fortschritt, primärer Fortschritt.

2. ProgressBar: Kotlin Main Activity Code

Schauen wir uns den Kotlin-Code der MainActivity.kt-Klasse an.

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 = "Vervollständigt $primaryProgressStatus% von 100"

                        if (primaryProgressStatus == 100) {
                            textViewPrimary.text = "Alle Aufgaben abgeschlossen"
                        }
                    }
                }
            }).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("Aktueller Aufgabenfortschritt\n$secondaryProgressStatus% von 100")

                    if (secondaryProgressStatus == 100) {
                        textViewSecondary.setText("Einzelaufgabe abgeschlossen.")
                    }
                }
            }
        }).start()
    }

    fun horizontalDeterminate(view: View) {
        isStarted = !isStarted
    }

}

Die Kotlin-Funktion horizontalDeterminate wird ausgelöst, wenn der erste Button geklickt wird. Sie wird verwendet, um die horizontale ProgressBar zu starten/zu stoppen. Ein Handler ist mit einem einzelnen Thread verbunden. Er wird verwendet, um Nachrichten an den Thread zu senden. Der btnProgressBarSecondary-Klick löst die zweite ProgressBar aus. Wir haben zwei Handler erstellt – einen für den normalen Fortschritt und einen für die Unteraufgaben. In beiden lassen wir den Thread schlafen. Für den sekundären Thread beträgt die Schlafzeit 1/100 des primären Fortschritts-Threads. Der Fortschrittswert wird auf dem TextView angezeigt.