Create a full page loading screen in Android

February 23, 2021

A typical loading screen best practices:

  • Prevent any further user interaction
  • Easily customisable
  • Easy show/hide logic

Let’s see how to create one in Android

Creating a Loading screen

Our loading screen in this example is going to be pretty straightforward. Full height and width container with a logo/image in between.

Tip: You can put a background color of black/white with 10% visibility to make rest of your app UI translucent and give the user an idea that UI is blocked for any further interaction.

<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/loading"
    android:background="#31000000"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@drawable/loading_background"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:src="@drawable/loading_image" />
    </RelativeLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

This is how our loading screen should look like:

But how to use this layout?

Using FrameLayout we can ensure that our loading screen UI comes on top of your app UI.

<FrameLayout 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">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

			<!-- Your rest of the App UI -->

    </androidx.constraintlayout.widget.ConstraintLayout>

    <androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/loading"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

			<!-- The Loading UI we defined above-->

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

How to block further user interaction?

Add a dummy touch listener to the loading layout.

loading_view.setOnTouchListener((view, motionEvent) -> true);

Making it easily customisable

DRY- Don’t repeat yourself.
We don’t need to put our loading screen xml in every layout. Let’s abstract it and use the tag to add our loading screen to any activity/fragment.

Define a separate xml file called loading.xml

<?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/loading"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <RelativeLayout
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="@drawable/loading_background"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

            <ImageView
                android:layout_width="60dp"
                android:layout_height="60dp"
                android:layout_centerHorizontal="true"
                android:layout_centerVertical="true"
                android:src="@drawable/digipay_logo" />
        </RelativeLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>

And include it in your activity/fragment like:

<?xml version="1.0" encoding="utf-8"?>
    <FrameLayout 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">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <!-- Your rest of the App UI -->

        </androidx.constraintlayout.widget.ConstraintLayout>

        <include
            android:id="@+id/loading"
            layout="@layout/loading"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="visible" />
    </FrameLayout>

Abstracting the show/hide logic

At this point, we can use the loading screen by simply setting loadingView.setVisibility(false|true) and our loading screen would work perfectly.

But wouldn’t it be nice if we had a simple API to handle visibility of our loading screen from anywhere inside our activity/fragment?

We’ll define a BaseActivity.java class, which inherits from the AppCompatActivity.java and extend/use that class in all of our activities. Similarly if we were working with fragments, we could create a BaseFragment class by extending the Fragment class.

public class MainActivity extends BaseActivity{

	ConstraintLayout loading_view;

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		loading_view = (ConstraintLayout) findViewById(R.id.loading);

		super.setView(loading_view);
	}
}

Here we’re calling a setView() method of our super class(BaseActivity.java), to let it recognise the view which is associated with the loading container.

And in our BaseActivity.java:

public class BaseActivity extends AppCompatActivity {
	ConstraintLayout loading_view = null;

	@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

	protected void setView(ConstraintLayout loading_view) {
		this.loading_view = loading_view;

		//To prevent user interaction
		loading_view.setOnTouchListener((view, motionEvent) -> true);
	}

	public void showLoading(boolean toShow) {
        if(loading_view!=null)
            loading_view.setVisibility(toShow ? View.VISIBLE : View.GONE);
    }
}

Now you can use the API showLoading(boolean) anywhere in your activity which extends our BaseActivity class and has been initiated with the loading screen view. Note that we can also abstract the code for setting the dummy onTouchListener in the BaseActivity class.


Written by Gagandeep Rangi who likes to talk about himself in third person. Twitter Instagram


Email icon