How to create a progress bar in an android app?

sajith eranda
4 min readAug 1, 2023

--

Step 1 — create a ProgressBar element

Navigate to the XML layout file where you want to add the progress bar. Typically, it would be your activity layout file (e.g., activity_main.xml).In the XML layout file, add the <ProgressBar> element to create the progress bar. Customize the attributes as needed

<ProgressBar
android:id="@+id/progressbar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="362dp"
android:background="@drawable/circularshape"
android:progress="0"
android:progressDrawable="@drawable/circularprogress" />

we also need to show the text value of the current progress bar.

<TextView
android:id="@+id/progresstext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="no data"
android:textColor="@color/black"
android:textSize="25dp"
android:textStyle="bold" />

You can apply any suitable width and height which we need to draw. we also need create background for the progress bar. then we can see the progress values very easily. then you can define circularsgape.xml file in drawable folder.

<?xml version="1.0" encoding="utf-8"?>

<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="ring"
android:innerRadiusRatio="2.7"
android:thickness="30dp"
android:useLevel="false"
>
<solid android:color="@color/dark_blue"/>
</shape>

In this shape we need to define shape as ring. We can use any thickness value which we want. We also need to define innerRadiusRatio correctly.you can also use any color for the background for the progress bar in this app.

We need to create a file in the drawable folder such as circularprogress.xml which we need to show values in progress bar.

<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="270"
android:toDegrees="270">

<shape
android:innerRadiusRatio="2.7"
android:shape="ring"
android:thickness="15dp"
android:useLevel="true">

<gradient
android:angle="0"
android:startColor="#D9E1E7"
android:endColor="#2697F0"
android:useLevel="false">
</gradient>

</shape>

</rotate>

· <?xml version=”1.0" encoding=”utf-8"?>: This is the XML declaration, indicating the version and encoding used in the XML file.

· <rotate xmlns:android=”http://schemas.android.com/apk/res/android" android:fromDegrees=”270" android:toDegrees=”270">: This is the <rotate> element that defines a rotation transformation applied to its children. The android:fromDegrees attribute specifies the starting rotation angle, and android:toDegrees attribute specifies the ending rotation angle. In this case, both are set to 270, which means there is no actual rotation.

· <shape android:innerRadiusRatio=”2.7" android:shape=”ring” android:thickness=”15dp” android:useLevel=”true”>: This is the <shape> element, defining a ring shape with specific properties:android:innerRadiusRatio: It sets the inner radius of the ring relative to the outer radius. In this case, it is set to 2.7, meaning the inner radius is 2.7 times smaller than the outer radius.

· android:shape: It specifies the shape of the drawable. Here, it is set to “ring” to create a ring shape.

· android:thickness: It determines the width of the ring. The value is set to 15dp, meaning the ring will have a thickness of 15 density-independent pixels.

· android:useLevel: It indicates whether the drawable should use the level specified

the XML code defines a custom drawable resource representing a ring-shaped progress indicator with a horizontal gradient that goes from light blue to dark blue.

Step 2- define id values

ProgressBar progressBar;
TextView progresstext;


protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

progressBar=findViewById(R.id.progressbar);
progresstext=findViewById(R.id.progresstext);


}

Step 3 — Create Runnable object to run show different values in every second

private void changeporgress() {


ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
Runnable task = () -> {
if (progress >= 100) {
progress = 0;
}
if (progress >= 0 && progress <= 100) {
runOnUiThread(() -> {
progressBar.setProgress(progress);
progresstext.setText(progress + "%");
});
progress+=5;
}
};

// Schedule the task to run every 1000 milliseconds (1 second)
executor.scheduleAtFixedRate(task, 0, 1000, TimeUnit.MILLISECONDS);
}

* ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);: This line creates a ScheduledExecutorService with a single thread that will be used to schedule tasks.

* Runnable task = () -> { … }: This creates a Runnable task using a lambda expression. The task contains the logic to update the progress.

* runOnUiThread(() -> { … });: This runs the specified code block on the main (UI) thread. Since UI updates should be done on the main thread in Android, this ensures that the progress bar and text are updated correctly.

  • executor.scheduleAtFixedRate(task, 0, 1000, TimeUnit.MILLISECONDS);: This schedules the task to run every 1000 milliseconds (1 second) with a fixed rate. So, the task (updating progress) will be executed repeatedly every second.
progress bar while running

here’s an example of a simple MainActivity.java code for an Android app

package com.example.sample_test;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.app.DatePickerDialog;
import android.app.TimePickerDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.DatePicker;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.TimePicker;

import java.util.Calendar;
import java.util.TimeZone;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity {

ProgressBar progressBar;
TextView progresstext;
int progress=0;


protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

progressBar=findViewById(R.id.progressbar);
progresstext=findViewById(R.id.progresstext);

changeporgress();



}

private void changeporgress() {


ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
Runnable task = () -> {
if (progress >= 100) {
progress = 0;
}
if (progress >= 0 && progress <= 100) {
runOnUiThread(() -> {
progressBar.setProgress(progress);
progresstext.setText(progress + "%");
});
progress+=5;
}
};

// Schedule the task to run every 1000 milliseconds (1 second)
executor.scheduleAtFixedRate(task, 0, 1000, TimeUnit.MILLISECONDS);
}
}

here’s an example of a simple activity_main.xmlcode for an Android app

<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="61dp">

<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="350dp"
android:layout_height="350dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.491"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.11"
tools:ignore="MissingConstraints">

<ProgressBar
android:id="@+id/progressbar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="362dp"
android:background="@drawable/circularshape"
android:progress="0"
android:progressDrawable="@drawable/circularprogress" />

<TextView
android:id="@+id/progresstext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="no data"
android:textColor="@color/black"
android:textSize="25dp"
android:textStyle="bold" />


</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

here’s an example of a simple circularshape.xmlcode for an Android app

<?xml version="1.0" encoding="utf-8"?>

<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="ring"
android:innerRadiusRatio="2.7"
android:thickness="30dp"
android:useLevel="false"
>
<solid android:color="@color/dark_blue"/>
</shape>

here’s an example of a simple circularprogress.xmlcode for an Android app

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="270"
android:toDegrees="270">

<shape
android:innerRadiusRatio="2.7"
android:shape="ring"
android:thickness="15dp"
android:useLevel="true">

<gradient
android:angle="0"
android:startColor="#D9E1E7"
android:endColor="#2697F0"
android:useLevel="false">
</gradient>

</shape>

</rotate>

--

--