Reputation: 9595
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
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
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
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
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