6

Sorry if this has been asked before but I cannot find the answer for this (I have searched!)

I have tried to follow the google/android documentation to make an indeterminate progressbar appear and spin while my app does a lengthy task.

protected void readData(final String whatToFind) 
{

    try
    {
        if (whatToFind.length() == 0)
        {
            adapter.notifyDataSetChanged();
            return;
        }


        mProgress.setVisibility(View.VISIBLE);
        mProgressText.setVisibility(View.VISIBLE);

        m_dialog = new ProgressDialog(this);
            m_dialog.setTitle("Searching...");
            m_dialog.setMessage("Please wait while searching...");
            m_dialog.setIndeterminate(true);
            m_dialog.setCancelable(true); 
            m_dialog.show(); 

        new Thread(new Runnable() 
        {
            public void run() 
            {
                mHandler.post(new Runnable() 
                {    
                    public void run() 
                    {

                                while (LotsOfWorkGoingOn)  
                                {
                                    // Update the progress bar
                                        mHandler.post(new Runnable() {
                                         public void run() {
                                             mProgress.setProgress(m_i); /// vain attempt to make the progressbar spin
                                         }
                                     });                                

                                                         mProgress.setVisibility(View.GONE);
                                                         mProgressText.setVisibility(View.GONE);
                                                         m_dialog.hide();

                                            }

                        });
            }
        }).start();

    }
    catch (Exception ex)
    {
        Log.e(LOGid, "Error listing items:" + ex.getStackTrace());
    }
Stephen Lacey
  • 107
  • 2
  • 2
  • 9

5 Answers5

9

setProgress only have effect when the progressbar is not Indeterminate.

Indeterminate means that, it has no progress amount, and it's used when you don't know the amount of progress done/remaining to end the task.

As stated in the documentation:

A progress bar can also be made indeterminate. In indeterminate mode, the progress bar shows a cyclic animation without an indication of progress. This mode is used by applications when the length of the task is unknown. The indeterminate progress bar can be either a spinning wheel or a horizontal bar.

On the other hand, if you don't even see the progress bar, maybe you have a light background?

Try to set the style attribute to:

style="@android:style/Widget.ProgressBar.Inverse"
Chopin
  • 1,442
  • 17
  • 24
  • Thanks Chopin, the progressbar appears, the thread executes, but the progressbar does not spin/animate, that's why (out of desperation) I added the "setProgress". Any idea why it would appear, but not animate the progressbar? – Stephen Lacey Apr 30 '12 at 22:47
  • Are you running this time-consuming task directly on the UI thread? If so, it will block the UI from any animation. – Chopin Apr 30 '12 at 23:02
  • The task is called from the UI thread allright, but I can't see a way around that as the action is the result of a UI click. I have encased the lengthy task inside: "new Thread(new Runnable() { public void run() { mHandler.post(new Runnable() { public void run() {" Type structure as per the google documentation... What is the alternative? – Stephen Lacey Apr 30 '12 at 23:19
  • Oh, I see that in the code. The other way is using [AsyncTask](http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html#AsyncTask). I think it's a more clever way. I'll post an example if you need one. – Chopin Apr 30 '12 at 23:27
  • Thanks Chpoin, I'd really appreciate an example - I've spent hours on this and nothing I have tried has made the progressbar animate. – Stephen Lacey Apr 30 '12 at 23:32
  • @StephenLacey posted an example in a separate answer. Hope that helps! – Chopin Apr 30 '12 at 23:59
8

Maybe I misunderstood the question, but for those that landed here trying to make their custom indeterminate ProgressBar spin, hopefully this helps you out. Set android:indeterminateDrawable not to the actual asset, but to your own custom drawable that ROTATES your asset.

Define res/drawable/progress_indeterminate_custom.xml:

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

When the task starts and ends, you can set the visibility of the ProgressBar to VISIBLE and GONE respectively.

If you want to modify the speed of the rotation, this answer says to change the toDegrees to multiples of 360 (ie. 720, 1080, etc).

Community
  • 1
  • 1
adamdport
  • 11,687
  • 14
  • 69
  • 91
8

In my case i simply forgot that all animations were disable on the device. Nothing blocking or any bad control setting.

MiguelSlv
  • 14,067
  • 15
  • 102
  • 169
5

Assuming there is an UI blocking issue, you can extend AsyncTask and use it in this way:

ProgressDialog m_dialog;

protected void readData(final String whatToFind) {

    if (whatToFind.length() == 0) {
        adapter.notifyDataSetChanged();
        return;
    }

    m_dialog = new ProgressDialog(this);
    new LengthyTask().execute();
}

//AsyncTask<Params, Progress, Result>
//Params: type passed in the execute() call, and received in the doInBackground method
//Progress: type of object passed in publishProgress calls
//Result: object type returned by the doInBackground method, and received by onPostExecute()
private class LengthyTask extends AsyncTask<Object, Integer, Object> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // initialize the dialog
        m_dialog.setTitle("Searching...");
        m_dialog.setMessage("Please wait while searching...");
        m_dialog.setIndeterminate(true);
        m_dialog.setCancelable(true);
        m_dialog.show();
    }

    @Override
    protected Object doInBackground(Object... params) {
        // do the hard work here
        // call publishProgress() to make any update in the UI
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        // called from publishProgress(), you can update the UI here
        // for example, you can update the dialog progress
        // m_dialog.setProgress(values[0]); --> no apply here, because we made it indeterminate
    }

    @Override
    protected void onPostExecute(Object result) {
        super.onPostExecute(result);

        // close the dialog
        m_dialog.dismiss();
        //do any other UI related task
    }
}

For a more in-depth explanation of AsyncTask, read here and here.

Chopin
  • 1,442
  • 17
  • 24
1

AsyncTask should do the trick, but I recommend Android Annotations to make this kind of thing a lot less verbose (and a lot easier).

void myMethod() {
    someBackgroundWork("hello", 42);
}

The thing to happen in the background:

@Background
void someBackgroundWork(String aParam, long anotherParam) {
    [...]
    doInUiThread("hello", 42);
}

Which can call something to happen in the UI thread.

@UiThread
void doInUiThread(String aParam, long anotherParam) {
    [...]
}

Android Annotations is probably worth it for this alone, but there are many other useful Annotations.

James
  • 1,985
  • 18
  • 19