How to retain component properties in screen rotate event? - android

I m very new to android development, i just make some simple application to practice which have "TextView" and "Button" in it. On each click the "TextSize" of TextView increase by 10. But after increasing TextSize when I rotate the screen the TextSize of TextView goes back default value.
Anybody please tell me how to handle this, so the TextView retain its size evenafter screen rotates.
-ZKhan

When you change the orientation then your onCreate() get called implicitly so to remove that
in your Manifest.xml just add this in application tag android:configChanges="orientation",
this tells the system that you are going to handle orientation by your own.
Then manage your logic in #Override onConfigurationChanged().

When configuration changed your activity is destroyed and it starts again from onCreate method.So you are seeing initial size.You can use below method to save the changed size and give it back while activity is again in onCreate.You can use shared preference to store changes
#Override
public void onConfigurationChanged(Configuration newConfig) {
}

Related

Device Orientation Destroy Activity

I've got my app working for the most part, but I've got buttons and text views with text that change based on some state variables. When I change the device's orientation it destroys and recreates the activity in the new orientation. I've tried adding
android:configChanges="orientation"
to the manifest file. I've also tried overriding the onConfigurationChanges method to "do nothing" but the text still reverts to default.
I know I can lock the user in to one orientation, but I would rather have the app usable in either orientation.
Alternatively, is there a way to determine which orientation the user opened the app in and lock them in that orientation until they restart the app?
Edit:
Thank you Kabir,
android:configChanges="orientation|screenSize"
works perfectly
For API 12 and below:
android:configChanges="orientation"
if you are targeting API 13 or above
android:configChanges="orientation|screenSize"
Actually orientation changing works by destroying and recreating an activity. Some views are able to save theirs states, others no. TextView doesn't save its state (in this case text) as it tends to show static text. If you want to save TextView's state during the configuration changes, you can do as following:
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
/*
1st argument is key, 2nd is value to save
*/
outState.putString("savedText", myTextView.getText().toString());
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
/*
The argument is key to get saved string
*/
myTextView.setText(savedInstanceState.getString("savedText"));
}
These onSaveInstanceState() and onRestoreInstanceState() are Activiy's methods.

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.
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.
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.
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

How to keep Popup window opened when orientation changes at run time in Android?

I have created a Popup window which contains month view to pick up date. When I changes orientation, due to Android loads an activity all over again my popup Window gets disappears. How can I make it opened even when orientation changes at runtime?
include android:configChanges="orientation" in your AndroidManifest.xml to the activity displaying window. Doing this tells android that you are going to handle orientation change yourself and eventually it will not destroy your activity and keeping the window displayed.
This technique is good if you dont have different layouts for portrait and landscape mode. However, if you do, you may still perform custom layout implementation by detecting the orientation mode as below:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
Log.i("orientation", "Orientation changed to: Landscape");
else
Log.i("orientation", "Orientation changed to: Portrait");
}
for preview, download and install this sample app.
Whenever there is an orientation change, Android destroys your activity ( calls onDestroy()) and then restarts it (calls onCreate()).
As soon as your popup is up, set a flag popup_open=1. Your popup will naturally have a dismiss button. Set the flag=0 in the click handler of this button. You can then re-open the popup when the app restarts in the method onRestoreInstanceState() or in the onCreate(). Here you would make a check for the flag. If the flag is set to 1, bring up the popup. So even if the orientation changed while the popup was up, onRestoreInstanceState() will know what to do based onthe state of the flag.
For more reference check: How to handle runtime changes.
Add this property to your activity in manifest.xml
android:configChanges="orientation|keyboard"
and that should do it.
Showing PopupWindow as
final View parent = findViewById(R.id.{parentId});
parent.post(new Runnable() {
#Override
public void run() {
mPopup.showAtLocation(parent, ...);
}
});
resolves unhandled exception on orientation change

Android : Save application state on screen orientation change

I have seen the following links before posting this question
http://www.devx.com/wireless/Article/40792/1954
Saving Android Activity state using Save Instance State
http://www.gitshah.com/2011/03/how-to-handle-screen-orientation_28.html
How to save state during orientation change in Android if the state is made of my classes?
I am not getting how should i override the following function :
#Override
public Object onRetainNonConfigurationInstance() {
return someExpensiveObject;
}
In my application i have layout with one editext visible and other editext get visible when the data of first editext validates to true.I have set the visbility of all other editextes and textviews to false and make them visible after validating.
So in my activity if the screen orientation is changed then all the items having android:visibility="false" get invisible.
I have also came to know that when our activities screen orientation changes it calls onStop() followed by onDestroy() and then again starts a fresh activity by calling onCreate()
This is the cause .. But i am not getting how to resolve it ..
Here You can see the screenshots of my application :
in this image all fields are loaded
and in another image when the screen orientation is changed to landscape they are all gone
Any link to tutorial or piece of code will be highly appreciable.
And also my application crashes when a progress dialog is shown up and i try to change screen orientation.How to handle this ??
Thanks
Well if you have the same layout for both screens then there is no need to do so just add below line in your manifest in Activity node
android:configChanges="keyboardHidden|orientation"
for Android 3.2 (API level 13) and newer:
android:configChanges="keyboardHidden|orientation|screenSize"
because the "screen size" also changes when the device switches between portrait and landscape orientation.
From documentation here: http://developer.android.com/guide/topics/manifest/activity-element.html
There is another possibility using which you can keep the state as it is even on Orientation change using the onConfigurationChanged(Configuration newConfig).
Called by the system when the device configuration changes while your activity is running. Note that this will only be called if you have selected configurations you would like to handle with the configChanges attribute in your manifest. If any configuration change occurs that is not selected to be reported by that attribute, then instead of reporting it the system will stop and restart the activity (to have it launched with the new configuration).
At the time that this function has been called, your Resources object will have been updated to return resource values matching the new configuration.
There are 2 ways of doing this, the first one is in the AndroidManifest.xml file. You can add this to your activity's tag. This documentation will give you an in depth explanation, but put simply it uses these values and tells the activity not to restart when one of these values changes.
android:configChanges="keyboardHidden|orientation|screenSize|screenLayout"
And the second one is: overriding onSaveInstanceState and onRestoreInstanceState. This method requires some more effort, but arguably is better. onSaveInstanceState saves the values set (manually by the developer) from the activity before it's killed, and onRestoreInstanceState restores that information after onStart() Refer to the official documentation for a more in depth look. You don't have to implement onRestoreInstanceState, but that would involve sticking that code in onCreate().
In my sample code below, I am saving 2 int values, the current position of the spinner as well as a radio button.
#Override
public void onSaveInstanceState(#NonNull Bundle savedInstanceState) {
spinPosition = options.getSelectedItemPosition();
savedInstanceState.putInt(Constants.KEY, spinPosition);
savedInstanceState.putInt(Constants.KEY_RADIO, radioPosition);
super.onSaveInstanceState(savedInstanceState);
}
// And we restore those values with `getInt`, then we can pass those stored values into the spinner and radio button group, for example, to select the same values that we saved earlier.
#Override
public void onRestoreInstanceState(#NotNull Bundle savedInstanceState) {
spinPosition = savedInstanceState.getInt(Constants.KEY);
radioPosition = savedInstanceState.getInt(Constants.KEY_RADIO);
options.setSelection(spinPosition, true);
type.check(radioPosition);
super.onRestoreInstanceState(savedInstanceState);
}

Kill an activity when orientation changes

I would like to know if it is possible to ask Android not to reload one Activity when orientation changes (I want to reload others but to kill this one !!).
I have checked the activity properties that I can set in the manifest but no one seems to allow that.
Thanks !
Try this:
public boolean onRetainNonConfigurationInstance() {
return true;
}
public onCreate() {
if(getLastNonConfigurationInstance() != null) {
finish();
}
}
It is simple, in your activity override onConfigurationChanged(Configuration config) and kill the activity inside of that.
Ex:
#Override
public void onConfigurationChanged (Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
finish();
}
This will cause the activity to be killed when a configuration change takes place. In the manifest under config changes select orientation for your activity. You can check which type of orientation it is changing to by looking at newConfig.orientation and compare it to the constants for portrait and landscape in the Configuration class.
I would like to know if it is possible to ask Android not to reload one Activity when orientation changes (I want to reload others but to kill this one !!).
Possible? Sure. A good idea? No. Users will get very confused if a simple twist of their wrist causes the current activity to go away. They might think that your app is broken.
Ideally, you allow users to use your activities in any orientation they desire. It is their device, not yours.
If, for some reason, some activity only makes sense in one orientation (e.g., landscape), use the android:orientation attribute in the <activity> element in the manifest to keep it in that orientation.

Categories

Resources