James B
James B

Reputation: 9595

Maintaining Progress Bar Visibility with Orientation Change

I have a progress bar (swirly waiting style) defined in xml as:

<ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@android:style/Widget.Holo.ProgressBar.Large"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:id="@+id/progress"
        />

I hide it's visibility in the activity's onCreate method using,

progressBar.setVisibility(View.GONE);

and start it on a button's onClick event using

progressBar.setVisibility(View.VISIBLE);

Now if I change the screen oreintation the progress bar disappears. I understand that the activity is destroyed and recreated on an orientation change, and the state of the activity is recreated in the new orientation from the saved Bundle savedInstanceState. So am I right in thinking that the default Bundle saved by android does not include any changes made to to a ProgressBar View object?

If this is the case, is it correct to say that the only way to reinstate the correct visibility of the ProgressBar after an orientation change is to save a flag (e.g. boolean pbState = false/true) by overriding the method onSaveInstanceState and inspecting this flag in onRestoreInstanceState and setting the visibility accordingly? Or, am I missing something really obvious about saving the state of view objects.

Thanks

UPDATE:

Both the solutions provided below work. I decided to opt for putting android:configChanges="orientation|screenSize" in the manifest xml file. However, the documentation states that this method should only be used as a last resort. My activity is fairly simple, and so the manifest xml method reduces the amount of code required in the main activity, i.e., no onRestoreInstanceState method. I presume if you're activity is more complex, you'll probably want to explicitly define any state changes using the latter method.

Upvotes: 2

Views: 4816

Answers (3)

Stephan
Stephan

Reputation: 1

Using android:configChanges is bad practice, because it might get you in much worse trouble.

Also saving a variable at onSaveInstanceState didn't work for me, since you won't get updates while the Activity is destroyed.

I ended up using a ResultReceiver inside a Fragment that doesn't get destroyed by using setRetainInstance(true).

A good article concerning this problem can be found here: https://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html

Also see my answer here: https://stackoverflow.com/a/54334864/6747171

Upvotes: 0

Vikram
Vikram

Reputation: 51571

So am I right in thinking that the default Bundle saved by android does not include any changes made to to a ProgressBar View object?

You are right. Android will not save the state of progressBar, or any other widget for that matter.

[Is] it correct to say that the only way to reinstate the correct visibility of the ProgressBar after an orientation change is to save a flag (e.g. boolean pbState = false/true) by overriding the method onSaveInstanceState and inspecting this flag in onRestoreInstanceState and setting the visibility accordingly?

Absolutely. About onRestoreInstanceState(Bundle): You can do without overriding this method. To confirm orientation change, check for savedInstanceState ==> Bundle passed to onCreate(Bundle) against null. If an orientation change has occurred, savedInstanceState will not be null. On start of an activity, savedInstanceState will be null. Following code (which is basically what you proposed) should do the job:

Declare a global boolean variable:

boolean progressBarIsShowing;

In your onCreate(Bundle):

// savedInstanceState != null ===>>> possible orientation change 
if (savedInstanceState != null && savedInstanceState.contains("progressbarIsShowing")) {

    // If `progressBarIsShowing` was stored in bundle, `progressBar` was showing
    progressBar.setVisibility(View.VISIBLE);

} else {

    // Either the activity was just created (not recreated), or `progressBar` wasn't showing
    progressBar.setVisibility(View.GONE);

}

Whenever you show progressBar, set progressBarIsShowing to true. And toggle it when you dismiss progressBar.

Override onSaveInstanceState(Bundle):

if (progressBarIsShowing) {
    outState.putBoolean("progressBarIsShowing", progressBarIsShowing);
}

Caution: Check for when user browses away from your activity(via home button press etc). You might get a BadTokenException if progressBar is showing when the user does so.

Upvotes: 7

Hariharan
Hariharan

Reputation: 24853

You use the following line inside your activity tag in manifest.

<activity android:name="your activity"
        android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"/>

In the above android:configChanges="orientation" will maintain the state of your application while configuration change.

Upvotes: 3

Related Questions