I am trying to implement orientation feature in the app. The app is basically made of tabs, using TabHost. Each tab is an activity group with a few activities. Each of this child activity runs a background task using AsyncTask to pull out server data and render the UI.
For instance,
HomeActivity- tab activity class that creates all the tabs
UserActivity- an activity group class representing a tab (say Tab 1)
TabOne- child activity inside UserActivity group
User sees Tab 1 soon after successful login. Issue begins when I tried to set orientation capabilities to this tab. Within the activity (TabOne), I added the following
#Override
public void onSaveInstanceState(Bundle outState) {
System.out.println("saving state..!");
outState.putStringArray("imageUrls", imageArray);
super.onSaveInstanceState(outState);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
System.out.println("restoring state..!");
imageArray = savedInstanceState.getStringArray("imageUrls");
super.onRestoreInstanceState(savedInstanceState);
}
I am able to obtain 'imageUrls' state. But, later down, I could not access the static tab host variable.
HomeActivity.tabHost.getTabWidget().getChildAt(1)
tabHost variable is null! I am not saving any of its state. How could I possibly save tabHost instance?
While researching other community posts, I found 'onRetainNonConfigurationInstance()'. I implemented the same.
public Object onRetainNonConfigurationInstance() {
System.out.println("retaining state..!");
return HomeActivity.tabHost;
}
Bu this object is returned as null. Can anyone walk me through steps to handle orientation changes in apps with tabHost?
Ask me if you find anything confusing.
Thanks in advance!
SOLVED: Adding screenSize to activity tag in the manifest fixed the issue.
<activity android:name=".HomeActivity"
android:configChanges="orientation|screenSize"/>
You can add the parameter
android:configChanges="orientation"
to your activity in manifest. I think it does what you want. It should look like:
<activity
android:name="com.your.package.YourActivity"
android:configChanges="orientation"
</activity>
Related
I would like to design a feed-based app with similar design like Facebook, Twitter or Instagram. In the main screen, I have a FeedActivity which holds a ViewPager for holding 3-4 fragments (represented as tabs)
FeedActivity
++ ListOfItemsFragment (there is a ListView holding posts)
++ OtherFragment
++ SomeOtherFragment
I would like to open another activity (or maybe another fragment in ViewPager) when a user touches a post (listed in ListOfItemsFragment). If I open this new activity (PostDetailActivity) and when I return to the FeedActivity, all data is lost in the ListOfItemsFragment because FeedActivity is created again.
Should I create a new Activity for the post detail, or should I add another fragment to FeedActivity independent of ViewPager (I want this fragment to be a popup, not a part of the tabs).
How can I support this behaviour?
Thanks.
Every time you press back the new Activity instance is created. Hense filled data erases. Just type the following lines in manifest file.
<activity android:name=".MainActivity"
android:launchMode="singleTop">
</activity>
Looking at the problem from a different perspective, sqlite is a solution.
Plus, there's an added bonus of storing states even if your app is completely destroyed and has to restart. See this SO thread.
Simply override this method and store that data that you want to display again
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putInt("intTag", intValue); // Save all the value that you want to retain
super.onSaveInstanceState(outState, outPersistentState);
}
and in you onCreate check if the savedInstanceState is not null than get the value and update your
if(savedInstanceState != null) {
int data = savedInstanceState.getInt("intTag");
// Retrieve all the data you have settled there
}
if the question sounds weird at first, here comes the explanation:
I have got an activity that hosts my three fragments. Since I would like one of my fragments to save its instance state when the device is rotated, I defined this in my manifest for my activity that hosts the fragments:
android:configChanges="orientation|screenSize"
This works just fine. However, now I have got an other problem: One of my other fragments uses a special landscape layout. The problem is, that this layout is not used immediately on device rotation. I think it is because the new layout only gets set on onCreate.
What can I do to solve this problem? I want my landscape layout to be set immediately.
You can put
setRetainInstance(true);
in onCreateView(); method of your Fragment. I think it should do the trick.
As far as I know you down need to add the configChanges parameter to your manifest.
You can override onSaveInstanceState() in your Fragment
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putInt(KEY_INDEX, someIntValue);
}
This methode should be called before your fragment gets destroyed.
Now in your onCreate(Bundle savedInstanceState) (or onCreateView()) methode:
if (savedInstanceState != null) {
someIntValue = savedInstanceState.getInt(KEY_INDEX);
}
This way it shouldn't intervene with any other special fragments.
I have an app that adds to a total variable when a button is clicked.
However if I turn my phone so the layout gets turned into the horizontal layout the values all get reset, and idea why this is and how to stop it?
Thanks!
When you move your device, your device's Orientation State changes from Portrait to Landscape of from Lanscape to Portrait.
In this Orientation change, your Activity's onCreate Method is called every time.
Therefore the values in your Activity are being reset.
There are 2 ways of solving this problem:
1) Let You Activity manage it for you.
2) Managing the changes yourself by saving and restoring states.
Using 1st way of solving this problem:
Just add this line in your Activity Node in your Manifest.xml file.
android:configChanges="orientation|keyboardHidden|screenSize"
For example:
<activity
android:name=".MyMainActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="#string/app_name" >
Using the second Way:
You can override these two Methods:
public void onSaveInstanceState(Bundle bundle) {
super.onSaveInstanceState(bundle);
//Manage your Data Explicitly here.
}
public void onRestoreInstanceState(Bundle bundle) {
super.onRestoreInstanceState(bundle);
//Manage your Data Explicitly here.
}
EDITAccording to Android Dev Guide:
Using android:configChanges="orientation|keyboardHidden|screenSize" is not a good practice.
Quote from this page
Note: Using this attribute should be avoided and used only as a last resort. Please read Handling Runtime Changes for more information about how to properly handle a restart due to a configuration change.
I recommend you to follow the Android Dev Guide for Handling Run-time Changes and follow the good Practices.
you need to save the variable in OnSaveInstanceState and restore it in onRestoreInstnace state
For example;
#Override
public void onSaveInstanceState(Bundle bundle) {
bundle.putParcelableArrayList(PEOPLE, people);
super.onSaveInstanceState(bundle);
}
#Override
public void onRestoreInstanceState(Bundle bundle) {
super.onRestoreInstanceState(bundle);
people = bundle.getParcelableArrayList(PEOPLE);
}
This happens because the normal way Android handles an activity during any configuration change (including screen reorientations) is to destroy the activity and recreate it. As described in the guide topic Handling Runtime Changes, you can handle it a couple of ways. The "Android way" is to save your activity's state information by overriding onSaveInstanceState and onRestoreInstanceState methods. The details about how to use these methods can be found in the guide topic Recreating an Activity.
The other way to prevent this problem is to tell Android that your activity will handle configuration changes internally. You do this by adding android:configChanges="orientation" to the <activity> tag in the manifest for the activity and overriding the onConfigurationChanged method of the activity to actually handle the changes.
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);
}
How do I retain the state of an activity in android? I have two layouts for portrait and landscape in layout and layout-land. I am loading the value from service at the time I am showing progress dialog. If loaded user rotates the device to landscape at the time also loading. How do I avoid that? user typed content in webview that also refreshed. How do I avoid that, can anybody provide an example?
Thanks
When orientation changes, the Activity is reloaded by default. If you do not want this behavior then add this to the Activity definition in your manifest:
android:configChanges="orientation|keyboardHidden"
For more detail, see Handling Runtime Changes
You can use the onRetainNonConfigurationChange() callback to store arbitrary data. It is called just before your application is about to be recreated.
Then, in onCreate() just check if some data were put aside by calling getLastNonConfigurationInstance() that returns the Object you put aside or null.
See this article on android developers.
Here's a sample borrowed from the link above:
#Override
public Object onRetainNonConfigurationInstance() {
//this is called by the framework when needed
//Just return what you want to save here.
return MyBigObjectThatContainsEverythingIWantToSave;
}
Automagic restore of previously saved state:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final MyDataObject MyBigObjectThatContainsEverythingIWantToSave = (MyDataObject) getLastNonConfigurationInstance();
if (MyBigObjectThatContainsEverythingIWantToSave == null) {
//No saved state
MyBigObjectThatContainsEverythingIWantToSave = loadMyData();
} else {
//State was restored, no need to download again.
}
...
}
When orientation changes, the Activity is reloaded by default. If you do not want this behavior then add this to the Activity definition in your android manifest file :
android:configChanges="orientation|screenSize|keyboardHidden"