Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android change ProgressDialog drawable while dialog works

I have a ProgressDialog which i started when Activity is Created(insideOnCreate method).

private void initDialog() {
    mProgressDialog = new ProgressDialog(this);
    mProgressDialog.setIndeterminate(true);
    mProgressDialog.setTitle("Please wait.");
    mProgressDialog.setMessage("Connecting to LinkedIn.");
    mProgressDialog.setCancelable(false);
    mProgressDialog.show();
}

After 2500ms i want to change a circle animation to my custom image(see below) (like an a simulation about when i finish retrieve some data from server and i'm done.) So i need to show user that process is finished. For this goal i select a next way.

  1. I show dialog
  2. When i retrieve data i change drawable of ProgressDialog

And this i have a problem. When i set the first time a drawable

private void initDialog() {
    mProgressDialog = new ProgressDialog(this);
    mProgressDialog.setIndeterminate(true);
    mProgressDialog.setTitle("Please wait.");
    mProgressDialog.setMessage("Connecting to LinkedIn.");
    mProgressDialog.setCancelable(false);
    //This
    mProgressDialog.setIndeterminateDrawable(getResources().getDrawable(R.drawable.ok));
    mProgressDialog.show();
}

ProgressDialog change drawable and all looks ok. But when ProgressBar launched(worked/circle animation playing) i try to reset a drawable

mProgressDialog.setIndeterminateDrawable(getResources().getDrawable(R.drawable.ok));

And i have unexpected result : circle animation disappear and no image set to current progress drawable. NO IMAGE! BLANK AREA instead of my image.

    authButton.postDelayed(new Runnable() {
        @Override
        public void run() {
            mProgressDialog.setIndeterminateDrawable(getResources().getDrawable(R.drawable.ok)); //doesn't work as expected!
        }
    }, 2500);

So my question is - how i can change drawable in runtime during ProgressDialog works?

enter image description here need to be changed to enter image description here

like image 700
Sergey Shustikov Avatar asked Mar 20 '15 16:03

Sergey Shustikov


2 Answers

Finally i find a solution

ProgressDialog contains inside a ProgressBar which display our drawable.

View view = inflater.inflate(a.getResourceId(com.android.internal.R.styleable.AlertDialog_horizontalProgressLayout, R.layout.alert_dialog_progress), null);
mProgress = (ProgressBar) view.findViewById(R.id.progress); // THIS
mProgressNumber = (TextView) view.findViewById(R.id.progress_number);
mProgressPercent = (TextView) view.findViewById(R.id.progress_percent);
setView(view);

When we try to set drawable again to ProgressDialog,ProgressDialog really set a new drawable. But this drawable didn't have a bounds (coordinates to display this view).
So we must set it hardly. I choose a copy way - just a copy bounds from current drawable of ProgressDialog. You can use another way.

Initialize dialog :

private void initDialog() {
    mProgressDialog = new ProgressDialog(this);
    mProgressDialog.setIndeterminate(true);
    mProgressDialog.setTitle("Please wait.");
    mProgressDialog.setMessage("Connecting to LinkedIn.");
    mProgressDialog.setCancelable(false);
}

Show

    mProgressDialog.show();

Change drawable

private void changeToDone(int resId) {
    //Getting a progressBar from dialog
    ProgressBar bar = (ProgressBar) mProgressDialog.findViewById(android.R.id.progress);
    //Getting a DONE(new) drawable from resources
    Drawable drawable = getResources().getDrawable(resId);
    //Getting a drawable from progress dialog
    Drawable indeterminateDrawable = bar.getIndeterminateDrawable();
    //Obtain a bounds of current drawable
    Rect bounds = indeterminateDrawable.getBounds();
    //Set bounds to DONE(new) drawable
    drawable.setBounds(bounds);
    //Set a new drawable
    bar.setIndeterminateDrawable(drawable);

    mProgressDialog.setTitle("Done.");
    mProgressDialog.setMessage("Connected.");
}

Note :

Solution untested on specific cases like an

  • We have a progress bar in ActionBar/TitleBar
  • Another cases when we already have an android.R.progress on the screen window. In this case i think my solution will be produce unexpected behavior.
like image 128
Sergey Shustikov Avatar answered Nov 03 '22 00:11

Sergey Shustikov


private void initDialog(boolean is) {
    mProgressDialog = new ProgressDialog(this);
    mProgressDialog.setIndeterminate(true);
    mProgressDialog.setTitle("Please wait.");
    mProgressDialog.setMessage("Connecting to LinkedIn.");
    mProgressDialog.setCancelable(false);
    if(is) // take global variable
    mProgressDialog.setIndeterminateDrawable(getResources().getDrawable(R.drawable.ic_launcher));
    mProgressDialog.show();
    if(!is)
    new Handler().postDelayed(new Runnable() {

        @Override
        public void run() {
            mProgressDialog.cancel();
            mProgressDialog = null;
            initDialog(true);   
        }
    }, 2500);

For first time call with initDialog(false);

As far as I checked indeterminate drawable cannot really be replaced, so this workaround can save you from creating custom ProgressBar.

like image 38
Satty Avatar answered Nov 03 '22 00:11

Satty