Display a loading overlay on Android screen

AndroidProgress BarOverlay

Android Problem Overview


I'm looking to display an overlay over the screen that shows a little loading ticker or possibly even some text whilst my app attempts to log into the server. My login screen is all inside of a vertical linear layout.

The effect I'm trying to achieve is something like this: http://docs.xamarin.com/recipes/ios/standard_controls/popovers/display_a_loading_message

Android Solutions


Solution 1 - Android

Maybe too late, but I guess somebody might find it useful.

Activity:

public class MainActivity extends Activity implements View.OnClickListener {

    String myLog = "myLog";

    AlphaAnimation inAnimation;
    AlphaAnimation outAnimation;

    FrameLayout progressBarHolder;
    Button button;

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

        button = (Button) findViewById(R.id.button);
        progressBarHolder = (FrameLayout) findViewById(R.id.progressBarHolder);

        button.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                new MyTask().execute();
                break;
        }

    }

    private class MyTask extends AsyncTask <Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            button.setEnabled(false);
            inAnimation = new AlphaAnimation(0f, 1f);
            inAnimation.setDuration(200);
            progressBarHolder.setAnimation(inAnimation);
            progressBarHolder.setVisibility(View.VISIBLE);
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            outAnimation = new AlphaAnimation(1f, 0f);
            outAnimation.setDuration(200);
            progressBarHolder.setAnimation(outAnimation);
            progressBarHolder.setVisibility(View.GONE);
            button.setEnabled(true);
        }

        @Override
        protected Void doInBackground(Void... params) {
            try {
                for (int i = 0; i < 5; i++) {
                    Log.d(myLog, "Emulating some task.. Step " + i);
                    TimeUnit.SECONDS.sleep(1);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

}

Layout xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start doing stuff"
        android:id="@+id/button"
        android:layout_below="@+id/textView"
        android:layout_centerHorizontal="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Do Some Stuff"
        android:id="@+id/textView"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />

    <FrameLayout
        android:id="@+id/progressBarHolder"
        android:animateLayoutChanges="true"
        android:visibility="gone"
        android:alpha="0.4"
        android:background="#000000"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ProgressBar
            style="?android:attr/progressBarStyleLarge"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:indeterminate="true"
            android:layout_gravity="center" />
    </FrameLayout>
</RelativeLayout>

Solution 2 - Android

I like the approach in Kostya But's answer.

Building on that, here's a couple of ideas to make the same overlay easily reusable across your app:

Consider putting the overlay FrameLayout in a separate layout file, e.g. res/layout/include_progress_overlay:

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/progress_overlay"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:alpha="0.4"
    android:animateLayoutChanges="true"
    android:background="@android:color/black"
    android:clickable="true"
    android:visibility="gone">

    <ProgressBar
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:indeterminate="true"/>

</FrameLayout>

(One thing I added in the overlay FrameLayout is android:clickable="true". So while the overlay is shown, it prevents clicks going through to UI elements underneath it. At least in my typical use cases this is what I want.)

Then include it where needed:

<!-- Progress bar overlay; shown while login is in progress -->
<include layout="@layout/include_progress_overlay"/>

And in code:

View progressOverlay;
[...]

progressOverlay = findViewById(R.id.progress_overlay);
[...]

// Show progress overlay (with animation): 
AndroidUtils.animateView(progressOverlay, View.VISIBLE, 0.4f, 200);
[...]

// Hide it (with animation): 
AndroidUtils.animateView(progressOverlay, View.GONE, 0, 200); 

With animation code extracted into a util method:

/**
 * @param view         View to animate
 * @param toVisibility Visibility at the end of animation
 * @param toAlpha      Alpha at the end of animation
 * @param duration     Animation duration in ms
 */
public static void animateView(final View view, final int toVisibility, float toAlpha, int duration) {
    boolean show = toVisibility == View.VISIBLE;
    if (show) {
        view.setAlpha(0);
    }
    view.setVisibility(View.VISIBLE);
    view.animate()
            .setDuration(duration)
            .alpha(show ? toAlpha : 0)
            .setListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            view.setVisibility(toVisibility);
        }
    });
}

(Here using view.animate(), added in API 12, instead of AlphaAnimation.)

Solution 3 - Android

I have ProgressBar in Relative Layout and I hide or show it respectively. And yes activity can be transparent.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <LinearLayout
        android:id="@+id/hsvBackgroundContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
    </LinearLayout>


    <ProgressBar
        android:id="@+id/pbProgess"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true" />

</RelativeLayout>

Solution 4 - Android

A spinner with a message over the application can be created using a ProgressDialog. Whilst it doesn't achieve the exact effect as in the picture, it's a good way to show that the app is working.

Solution 5 - Android

I made a library (Not well documented yet, Do it within a few days after reducing some work pressure) to do this kind of progress dialog. I made it the very reusable way that's why you need to just configure it one time and hide show it anywhere in your app just calling a single line of code. The configuration -

 LoadingPopup.getInstance(this)
                .customLoading()
               .setCustomViewID(R.layout.yourProgressLayout,R.color.yourProgressBackgroundColor)
                .doIntentionalDelay()
                .setDelayDurationInMillSec(5000)
                .setBackgroundOpacity(70)/*How much transparent you want your background*/
                .build();

For showing the progress -

LoadingPopup.showLoadingPopUp();

For hiding the progress-

LoadingPopup.hideLoadingPopUp();

Solution 6 - Android

I had the same question, I tried the solutions but was not the best UI so, I did the followings steps.

  1. Divide the screen in 2 views: Content and ProgressBar.
  2. When you want to call the ProgressBar you change the visibility to VISIBLE and add the following properties to the content id=content and not to the progressBar container.

content.background="#000000" content.alpha="0.4"

<FrameLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <RelativeLayout
            android:id="@+id/content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:animateLayoutChanges="true"
            tools:context=".MainActivity">
    
            <Button
                android:id="@+id/button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/textView"
                android:layout_centerHorizontal="true"
                android:text="Start doing stuff" />
    
            <TextView
                android:id="@+id/textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                android:layout_centerHorizontal="true"
                android:text="Do Some Stuff"
                android:textAppearance="?android:attr/textAppearanceLarge" />
    
        </RelativeLayout>
    
        <ProgressBar
            style="?android:attr/progressBarStyleLarge"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:indeterminate="true"
            android:visibility="gone" />
    
    </FrameLayout>

Solution 7 - Android

You have to make a background operation using thread concept like AsyncTask. Using this you can hide the actual work from the UI part. And AsyncTask will get unallocated after your operations are completed.

  • Create a subclass of AsyncTask
  • Use AsyncTask to do background work
  • Call onPreExecute() to initialize task
  • Use a progressbar with setIndeterminate(true) to enable the indeterminate mode
  • Call onProgressUpdate() to animate your progressbar to let the user know some work is being done
  • Use incrementProgressBy() for increment progressbar content by a specific value
  • Call doInBackground()and do the background work here
  • Catch an InterruptedException object to find end of background operation
  • Call onPostExecute() to denote the end of operation and show the result

Android's indeterminate ProgressDialog tutorial

Splash screen while loading resources in android app

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJames MongerView Question on Stackoverflow
Solution 1 - AndroidKostya ButsView Answer on Stackoverflow
Solution 2 - AndroidJonikView Answer on Stackoverflow
Solution 3 - AndroidMalachiaszView Answer on Stackoverflow
Solution 4 - AndroidJames MongerView Answer on Stackoverflow
Solution 5 - AndroidGk Mohammad EmonView Answer on Stackoverflow
Solution 6 - AndroidEmiliano SchiavoneView Answer on Stackoverflow
Solution 7 - AndroidYash KrishnanView Answer on Stackoverflow