Custom Progress Bar in Android

Filed Under: Android

Custom progress bar in android application gives it a personal touch. In this tutorial, we’ll create a custom progress bar by implementing a spinning logo icon in our application. Most of the time, we end up using a ProgressBar as the loading icon while the data gets loaded. Going by the current trend, apps like Reddit, UBER, Foodpanda and Twitter have replaced the commonly used Progress Bar with their application’s icon as the loading icon. This gives their application as well as logo brand a touch that makes them stand out from the rest.

Custom Progress Bar in Android

Let’s see the classical way of showing a loading icon in our application’s activity.
android progress bar example

The code for the layout above should look like this:


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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="com.journaldev.spinninglogo.MainActivity">

    <ProgressBar
        android:id="@+id/progressBarLarge"
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ProgressBar
        android:id="@+id/progressBarSmall"
        style="?android:attr/progressBarStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/progressBarLarge" />

    <ProgressBar
        android:id="@+id/progressBarMedium"
        style="?android:attr/progressBarStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toTopOf="@+id/progressBarLarge"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

</android.support.constraint.ConstraintLayout>

We’ve set three circular ProgressBars that rotate endlessly in the above layout. Now let’s try to add a ProgressBar that spins an icon indeterminately.

Custom Progress Bar Android Studio Project Structure

custom progress bar in android studio project structure

Android Custom Progress Bar Code

The ProgressBar class contains an attribute indeterminateDrawable which replaces the default indicator with the drawable specified. Let’s see what happens when we place an icon in the ProgressBar.

The code for activity_main.xml looks like this:


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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="com.journaldev.spinninglogo.MainActivity">

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:indeterminateDrawable="@mipmap/ic_launcher"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

The output that the above layout reflects in our application is given below.
android progressbar drawable output

Oops! What’s wrong with the ProgressBar? Why isn’t it rotating?

Well we need to set a RotateDrawable as the value of the attribute.

A RotateDrawable is defined in the xml by encapsulating the current drawable and assigning it the angle and degrees of rotation. The tag <rotate> is used to do so in the xml as shown below.

The code for the progress_icon.xml RotateDrawable is given below.


<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item>
        <rotate
            android:drawable="@mipmap/ic_launcher"
            android:fillAfter="true"
            android:fromDegrees="0"
            android:pivotX="50%"
            android:pivotY="50%"
            android:toDegrees="360" />
    </item>
</layer-list>

The attribute android:fillAfter indicates that the transformation is applied after the
animation is over.

android:toDegrees value can be increased or decreased to change the speed of rotation. Generally it’s recommended to set it in multiples of 360.

Let’s set the above drawable in the ProgressBar present in the activity_main.xml.


    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:indeterminateDrawable="@drawable/progress_icon"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

The output reflected in the application is shown below.
android spinning image, android rotate image animation

Let’s create a basic application that displays a string in a TextView from an ArrayList after a delay.

The code for the xml layout file activity_main.xml is given below.


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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="com.journaldev.spinninglogo.MainActivity">

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:indeterminateDrawable="@drawable/progress_icon"
        android:visibility="gone"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="32dp"
        android:text="TAP ME TO GET A RANDOM QUOTE"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="A Greeting Message Awaits You"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

Take note of the efficient use of ConstraintLayout in the above code.

The code for the MainActivity.java is given below.


package com.journaldev.spinninglogo;

import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {


    TextView textView;
    List<String> quotesList;
    ProgressBar progressBar;
    int i = 0;

    Handler handler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        quotesList = new ArrayList<>();

        quotesList.add("Hi");
        quotesList.add("Happy New Year");
        quotesList.add("Hope you have a good day");
        quotesList.add("Merry Christmas");

        Button btnTap = findViewById(R.id.button);
        textView = findViewById(R.id.textView);
        progressBar = findViewById(R.id.progressBar);


        btnTap.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                progressBar.setVisibility(View.VISIBLE);
                textView.setVisibility(View.GONE);
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {

                        if (i == quotesList.size())
                            i = 0;

                        textView.setVisibility(View.VISIBLE);
                        textView.setText(quotesList.get(i++));
                        progressBar.setVisibility(View.GONE);

                    }
                }, 3000);
            }
        });

    }


}

The output of the above application in action is given below.

android custom progress bar example

Note: Ignore the flickering rotation in the gifs. It’s absolutely smooth when running on a device.

This brings an end to this tutorial. We’ve implemented a RotationDrawable inside a ProgressBar to achieve a spinning logo like indicator. This should be good for showing a loading progress in apps.

You can download the final Android Custom Progress Bar project from the link below.

Reference: API Doc

Comments

  1. Gurpreet Singh says:

    I am not proper understand your program code………Please explain it brefily…If it is possible for you!

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages