Using the "animated circle" in an ImageView while loading stuff

AndroidLoadingAndroid AsynctaskGeometry

Android Problem Overview


I am currently using in my application a listview that need maybe one second to be displayed.

What I currently do is using the @id/android:empty property of the listview to create a "loading" text.

 <TextView android:id="@id/android:empty"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:background="#FF0000"
           android:text="Loading..."/>

Now, I would like to replace that with the animated circle that is used in a loading dialog instead of this text, i guess you all know what I mean:

Edit: I do not want a dialog. I want to show that inside my layout.

http://flexfwd.com/DesktopModules/ATI_Base/resources/images/loading_blue_circle.gif

Thank a lot for your help!

Android Solutions


Solution 1 - Android

Simply put this block of xml in your activity layout file:

<RelativeLayout
    android:id="@+id/loadingPanel"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center" >

    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:indeterminate="true" />
</RelativeLayout>

And when you finish loading, call this one line:

findViewById(R.id.loadingPanel).setVisibility(View.GONE);

The result (and it spins too):

enter image description here

Solution 2 - Android

You can do this by using the following xml

<RelativeLayout
    style="@style/GenericProgressBackground"
    android:id="@+id/loadingPanel"
    >
    <ProgressBar
        style="@style/GenericProgressIndicator"/>
</RelativeLayout>

With this style

<style name="GenericProgressBackground" parent="android:Theme">
	<item name="android:layout_width">fill_parent</item>	
	<item name="android:layout_height">fill_parent</item>
	<item name="android:background">#DD111111</item>	
	<item name="android:gravity">center</item> 	
</style>
<style name="GenericProgressIndicator" parent="@android:style/Widget.ProgressBar.Small">
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:indeterminate">true</item> 
</style>

To use this, you must hide your UI elements by setting the visibility value to GONE and whenever the data is loaded, call setVisibility(View.VISIBLE) on all your views to restore them. Don't forget to call findViewById(R.id.loadingPanel).setVisiblity(View.GONE) to hide the loading animation.

If you dont have a loading event/function but just want the loading panel to disappear after x seconds use a Handle to trigger the hiding/showing.

Solution 3 - Android

This is generally referred to as an Indeterminate Progress Bar or Indeterminate Progress Dialog.

Combine this with a Thread and a Handler to get exactly what you want. There are a number of examples on how to do this via Google or right here on SO. I would highly recommend spending the time to learn how to use this combination of classes to perform a task like this. It is incredibly useful across many types of applications and will give you a great insight into how Threads and Handlers can work together.

I'll get you started on how this works:

The loading event starts the dialog:

//maybe in onCreate
showDialog(MY_LOADING_DIALOG);
fooThread = new FooThread(handler);
fooThread.start();

Now the thread does the work:

private class FooThread extends Thread {
    Handler mHandler;
   
    FooThread(Handler h) {
        mHandler = h;
    }
   
    public void run() { 
        //Do all my work here....you might need a loop for this

        Message msg = mHandler.obtainMessage();
        Bundle b = new Bundle();           	    
        b.putInt("state", 1);	
        msg.setData(b);
        mHandler.sendMessage(msg);
    }
}

Finally get the state back from the thread when it is complete:

final Handler handler = new Handler() {
    public void handleMessage(Message msg) {
        int state = msg.getData().getInt("state");
        if (state == 1){
        	dismissDialog(MY_LOADING_DIALOG);
        	removeDialog(MY_LOADING_DIALOG);
        }
    }
};

Solution 4 - Android

You can use this code from firebase github samples ..

You don't need to edit in layout files ... just make a new class "BaseActivity"

package com.example;

import android.app.ProgressDialog;
import android.support.annotation.VisibleForTesting;
import android.support.v7.app.AppCompatActivity;


public class BaseActivity extends AppCompatActivity {

    @VisibleForTesting
    public ProgressDialog mProgressDialog;

    public void showProgressDialog() {
        if (mProgressDialog == null) {
            mProgressDialog = new ProgressDialog(this);
            mProgressDialog.setMessage("Loading ...");
            mProgressDialog.setIndeterminate(true);
        }

        mProgressDialog.show();
    }


    public void hideProgressDialog() {
        if (mProgressDialog != null && mProgressDialog.isShowing()) {
            mProgressDialog.dismiss();
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        hideProgressDialog();
    }

}

In your Activity that you want to use the progress dialog ..

public class MyActivity extends BaseActivity

Before/After the function that take time

showProgressDialog();
.... my code that take some time
showProgressDialog();

Solution 5 - Android

If you would like to not inflate another view just to indicate progress then do the following:

  1. Create ProgressBar in the same XML layout of the list view.
  2. Make it centered
  3. Give it an id
  4. Attach it to your listview instance variable by calling setEmptyView

Android will take care the progress bar's visibility.

For example, in activity_main.xml:

    <?xml version="1.0" encoding="utf-8"?>
<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"
    android:orientation="vertical"
    tools:context="com.fcchyd.linkletandroid.MainActivity">

    <ListView
        android:id="@+id/list_view_xml"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="@color/colorDivider"
        android:dividerHeight="1dp" />

   <ProgressBar
        android:id="@+id/loading_progress_xml"
        style="?android:attr/progress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true" />

</RelativeLayout>

And in MainActivity.java:

package com.fcchyd.linkletandroid;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;

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

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class MainActivity extends AppCompatActivity {

final String debugLogHeader = "Linklet Debug Message";
Call<Links> call;
List<Link> arraylistLink;
ListView linksListV;

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

    linksListV = (ListView) findViewById(R.id.list_view_xml);
    linksListV.setEmptyView(findViewById(R.id.loading_progress_xml));
    arraylistLink = new ArrayList<>();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://api.links.linklet.ml")
            .addConverterFactory(GsonConverterFactory
                    .create())
            .build();

    HttpsInterface HttpsInterface = retrofit
            .create(HttpsInterface.class);

    call = HttpsInterface.httpGETpageNumber(1);

    call.enqueue(new Callback<Links>() {
        @Override
        public void onResponse(Call<Links> call, Response<Links> response) {
            try {
                arraylistLink = response.body().getLinks();

                String[] simpletTitlesArray = new String[arraylistLink.size()];
                for (int i = 0; i < simpletTitlesArray.length; i++) {
                    simpletTitlesArray[i] = arraylistLink.get(i).getTitle();
                }
                ArrayAdapter<String> simpleAdapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, simpletTitlesArray);
                linksListV.setAdapter(simpleAdapter);
            } catch (Exception e) {
                Log.e("erro", "" + e);
            }
        }

        @Override
        public void onFailure(Call<Links> call, Throwable t) {

        }
    });


}

}

Solution 6 - Android

For the ones developing in Kotlin, there is a sweet method provided by the Anko library that makes the process of displaying a ProgressDialog a breeze!

Based on that link:

val dialog = progressDialog(message = "Please wait a bit…", title = "Fetching data")
dialog.show()
//....
dialog.dismiss()

This will show a Progress Dialog with the progress % displayed (for which you have to pass the init parameter also to calculate the progress).

There is also the indeterminateProgressDialog() method, which provides the Spinning Circle animation indefinitely until dismissed:

indeterminateProgressDialog("Loading...").show()

Shout out to this blog which led me to this solution.

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
QuestionWaza_BeView Question on Stackoverflow
Solution 1 - Androiduser1032613View Answer on Stackoverflow
Solution 2 - AndroidKurruView Answer on Stackoverflow
Solution 3 - Androiduser432209View Answer on Stackoverflow
Solution 4 - AndroidkhateebView Answer on Stackoverflow
Solution 5 - AndroidMd_Zubair AhmedView Answer on Stackoverflow
Solution 6 - AndroidDarkCygnusView Answer on Stackoverflow