I am writing a phone dialer app for android. I created a layout for keypad, which contains a TextView and 10 buttons. Buttons are as keys for 10 digits(0 to 9) and TextView is for displaying the number according to keys pressed.
In my app, i am appending the text ("0" or "1", etc.) to the TextView for each button pressed. If i pressed the buttons 1, 2, 3 then the text on TextView is 123.
The problem is, let's take the screen is in landscape mode and TextView contains 123, if i turn it, in portrait mode no text on TextView.
Please Help Me Regarding this.
What #jeet recommended didn't work for me. I had to add "screenSize". This is the line you should add in your manifest.xml in the <activity> node of your activity:
android:configChanges="keyboardHidden|orientation|screenSize"
Thus, the complete node may look like this:
<activity
android:name=".YourActivity"
android:label="#string/app_name"
android:configChanges="keyboardHidden|orientation|screenSize"
android:theme="#style/AppTheme.NoActionBar">
Please check on orientation change, on create method is called, which requires all the views to be created again, so you need to use one of the following methods:
use onSavedInstance method and save the states of components/views to bundle.
Just use following flag true in your manifest file in activity tag android:configChanges="keyboardHidden|orientation". like below:
<activity android:name=".SampleActivity" android:label="#string/app_name"
android:configChanges="keyboardHidden|orientation">
...
</activity>
The reason for this is due to Android basically destroying the activity and creating it again every time you rotate the device. This is mainly to allow for different layouts based on portrait/landscape mode.
The best way to handle this is to store whatever data you need to keep within the Activity Bundle, by responding to the onSavedInstance event (called just before Android destroys the activity), and then reapplying those in the standard onCreate event.
Although you can add "orientation" to the configChanges property, keep in mind that you're basically telling Android that you're going to be handling everything relating to orientation change yourself - including changing layout, etc.
To preserve a TextView's text, you can simply set the TextView's freezesText property to true.
As in:
<TextView
...
android:freezesText="true"
.../>
This is the accepted answer here:
Restoring state of TextView after screen rotation?
If someone is still having troubles... this did the trick for me
public class BranjeKP extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_branje_kp);
//...
}
#Override
protected void onSaveInstanceState(Bundle out) {
super.onSaveInstanceState(out);
out.putString("TVNazivPod", TVNazivPodatka.getText().toString());
out.putString("TVEnotaMere", TVEnotaMere.getText().toString());
}
#Override
protected void onRestoreInstanceState(Bundle in) {
super.onRestoreInstanceState(in);
TVNazivPodatka.setText(in.getString("TVNazivPod"));
TVEnotaMere.setText(in.getString("TVEnotaMere"));
}
You basically save any values you want before rotation (that's when onSaveInstanceState is called) into a Bundle and after rotation (onRestoreInstanceState) you just pull all values out from Bundle.
Just to clarify, TVNazivPodatka and TVEnotaMere are TextView widgets.
...with a help from
How to prevent custom views from losing state across screen orientation changes
Related
In my app I have TextView and EditText. Both have data in it. When the screen orientation changes the data in the EditText remains, but TextView data is cleared.
Can some one help me out to find a way to retain data in TextView too?
If you want to force your TextView to save its state you must add freezesText attribute:
<TextView
...
android:freezesText="true" />
From documentation on freezesText :
If set, the text view will include its current complete text inside of its frozen icicle in addition to meta-data such as the current cursor position. By default this is disabled; it can be useful when the contents of a text view is not stored in a persistent place such as a content provider
In order to retain data on orientation change you need to implement the two methods:
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Read values from the "savedInstanceState"-object and put them in your textview
}
#Override
protected void onSaveInstanceState(Bundle outState) {
// Save the values you need from your textview into "outState"-object
super.onSaveInstanceState(outState);
}
1) Not all views with an ID save their state. Android widgets, with an ID, whose state can be changed by the user, appear to save their state on a soft kill. So EditText saves its state, but TextView does not save its state on a soft kill.
"AFAIK, Android only bothers saving state for things that are expected to
change. That is why it saves the text in an EditText (which a user is
likely to change) and perhaps does not save the state for a TextView (which normally stays static)"
Mark M
So you may choose to save the state of the textview in onSaveInstanceState and you may choose to restore the state of the textview in onCreate.
2) Best practice is to save "internal" non view instance state even if you declare
android:configChanges= "orientation|keyboardHidden"
From the docs:
"However, your application should always be able to shutdown and restart with its previous state intact. Not only because there are other configuration changes that you cannot prevent from restarting your application but also in order to handle events such as when the user receives an incoming phone call and then returns to your application."
JAL
Android does not handle that kind of stuff for you. You have save all data manually.
You can use in a activity to save values
#Override
public Object onRetainNonConfigurationInstance() {
HashMap<String, Object> savedValues = new HashMap<String, Object>();
savedValues.put("someKey", someData);
return savedValues;
}
and use something like this in the oncreate method of a activity to load the saved objects
HashMap < String, Object> savedValues
= (HashMap<String, Object>)this.getLastNonConfigurationInstance();
you can also choose the disable orientation change for an activity
<activity android:name=".Activity" android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
Modify your activities in AndroidManifest.xml to override orientation change behavior by adding this to your activity/activities:
android:configChanges="orientation|keyboardHidden"
It should look somewhat like this:
<activity android:name=".activity.LoginActivity"
android:configChanges="orientation|keyboardHidden"
android:label="#string/app_name">
</activity>
Add these to AndroidManifest.xml
Put your Activity Name in the place of Activity_Name
<activity android:name="Activity_Name"
android:screenOrientation="sensor"
...
android:configChanges="orientation|keyboardHidden|screenSize">
This will work with value changing TextField also.
just add
android:configChanges="orientation|screenSize"
to your Activity in AndroidManifest.xml.
When configuration changes Android restarts your activity by default. To change this you should override onConfigurationChanged() method. Also, you should add android:configChanges to your manifest file.
You can read more here.
I also used
android:configChanges="orientation"
and it did not work.
But then I found a solution.
Verify if you have the following line correctly in your maniest:
<uses-sdk android:minSdkVersion="11" android:targetSdkVersion="11" />
make sure it does not read something like
<uses-sdk android`:minSdkVersion="11" android:targetSdkVersion="15" />`
I had it the second way in first place but when I corrected it state got preserved.
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);
}
I simply need nothing to change when the screen is rotated. My app displays a random image when it first loads and rotating the device should not select another random image.
How can I (simply) make this behavior stop?
There are generally three ways to do this:
As some of the answers suggested, you could distinguish the cases of your activity being created for the first time and being restored from savedInstanceState. This is done by overriding onSaveInstanceState and checking the parameter of onCreate.
You could lock the activity in one orientation by adding android:screenOrientation="portrait" (or "landscape") to <activity> in your manifest.
You could tell the system that you meant to handle screen changes for yourself by specifying android:configChanges="orientation|screenSize" in the <activity> tag. This way the activity will not be recreated, but will receive a callback instead (which you can ignore as it's not useful for you).
Personally I'd go with (3). Of course if locking the app to one of the orientations is fine with you, you can also go with (2).
Xion's answer was close, but #3 (android:configChanes="orientation") won't work unless the application has an API level of 12 or lower.
In API level 13 or above, the screen size changes when the orientation changes, so this still causes the activity to be destroyed and started when orientation changes.
Simply add the "screenSize" attribute like I did below:
<activity
android:name=".YourActivityName"
android:configChanges="orientation|screenSize">
</activity>
Now, when you change orientation (and screen size changes), the activity keeps its state and onConfigurationChanged() is called. This will keep whatever is on the screen (ie: webpage in a Webview) when the orientation changes.
Learned this from this site:
http://developer.android.com/guide/topics/manifest/activity-element.html
Also, this is apparently a bad practice so read the link below about Handling Runtime Changes:
http://developer.android.com/guide/topics/resources/runtime-changes.html
You just have to go to the AndroidManifest.xml and inside or in your activities labels, you have to type this line of code as someone up there said:
android:configChanges="orientation|screenSize"
So, you'll have something like this:
<activity android:name="ActivityMenu"
android:configChanges="orientation|screenSize">
</activity>
Hope it works!
<activity android:name="com.example.abc"
android:configChanges="orientation|screenSize"></activity>
Just add android:configChanges="orientation|screenSize" in activity tab of manifest file.
So, Activity won't restart when orientation change.
It's my experience that it's actually better to just deal with the orientation changes properly instead of trying to shoehorn a non-default behavior.
You should save the image that's currently being displayed in onSaveInstanceState() and restore it properly when your application runs through onCreate() again.
This solution is by far the best working one. In your manifest file add
<activity
android:configChanges="keyboardHidden|orientation|screenSize"
android:name="your activity name"
android:label="#string/app_name"
android:screenOrientation="landscape">
</activity
And in your activity class add the following code
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
//your code
} else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
//your code
}
}
In manifiest file add to each activity this. This will help
android:configChanges = "orientation|keyboard|keyboardHidden|screenLayout|screenSize"
add android:configChanges="keyboardHidden|orientation|screenSize" for all the app activities tags in manifest.
Just add this to your AndroidManifest.xml
<activity android:screenOrientation="landscape">
I mean, there is an activity tag, add this as another parameter. In case if you need portrait orientation, change landscape to portrait. Hope this helps.
just use : android:configChanges="keyboardHidden|orientation"
As Pacerier mentioned,
android:configChanges="orientation|screenSize"
All above answers are not working for me. So, i have fixed by mentioning the label with screenOrientation like below. Now everything fine
<activity android:name=".activity.VideoWebViewActivity"
android:label="#string/app_name"
android:configChanges="orientation|screenSize"/>
http://animeshrivastava.blogspot.in/2017/08/activity-lifecycle-oncreate-beating_3.html
#Override
protected void onSaveInstanceState(Bundle b)
{
super.onSaveInstanceState(b);
String str="Screen Change="+String.valueOf(screenChange)+"....";
Toast.makeText(ctx,str+"You are changing orientation...",Toast.LENGTH_SHORT).show();
screenChange=true;
}
Prevent Activity to recreated
Most common solution to dealing with orientation changes by setting the android:configChanges flag on your Activity in AndroidManifest.xml. Using this attribute your Activities wonβt be recreated and all your views and data will still be there after orientation change.
<activity
android:name="com.example.test.activity.MainActivity"
android:configChanges="orientation|screenSize|keyboardHidden"/>
this is work for meπππ
Save the image details in your onPause() or onStop() and use it in the onCreate(Bundle savedInstanceState) to restore the image.
EDIT:
More info on the actual process is detailed here http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle as it is different in Honeycomb than previous Android versions.
I dont know if the a best solution, but i describe it here:
First of all, you need certificate with you class Application of your app is in your manifest of this:
<application
android:name=".App"
...
Second, in my class App i did like this:
public class App extends Application {
public static boolean isOrientationChanged = false;
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onConfigurationChanged(#NotNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE ||
newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
isOrientationChanged = true;
}
}
}
Third, you need to set a flag to Orientation Change, in my case, I always set it when the previous activity within the app navigation is called, so only calling once when the later activity is created.
isOrientationChanged = false;
So every time I change the orientation of my screen in that context, I set it every time it changes this setting, it checks if there is a change in orientation, if so, it validates it based on the value of that flag.
Basically, I had to use it whenever I made an asynchronous retrofit request, which he called every moment that changed orientation, constantly crashing the application:
if (!isOrientationChanged) {
presenter.retrieveAddress(this, idClient, TYPE_ADDRESS);
}
I don't know if it's the most elegant and beautiful solution, but at least here it's functional :)
Add this code after the onCreate ,method in your activity containing the WebView
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
}
In my app I have TextView and EditText. Both have data in it. When the screen orientation changes the data in the EditText remains, but TextView data is cleared.
Can some one help me out to find a way to retain data in TextView too?
If you want to force your TextView to save its state you must add freezesText attribute:
<TextView
...
android:freezesText="true" />
From documentation on freezesText :
If set, the text view will include its current complete text inside of its frozen icicle in addition to meta-data such as the current cursor position. By default this is disabled; it can be useful when the contents of a text view is not stored in a persistent place such as a content provider
In order to retain data on orientation change you need to implement the two methods:
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Read values from the "savedInstanceState"-object and put them in your textview
}
#Override
protected void onSaveInstanceState(Bundle outState) {
// Save the values you need from your textview into "outState"-object
super.onSaveInstanceState(outState);
}
1) Not all views with an ID save their state. Android widgets, with an ID, whose state can be changed by the user, appear to save their state on a soft kill. So EditText saves its state, but TextView does not save its state on a soft kill.
"AFAIK, Android only bothers saving state for things that are expected to
change. That is why it saves the text in an EditText (which a user is
likely to change) and perhaps does not save the state for a TextView (which normally stays static)"
Mark M
So you may choose to save the state of the textview in onSaveInstanceState and you may choose to restore the state of the textview in onCreate.
2) Best practice is to save "internal" non view instance state even if you declare
android:configChanges= "orientation|keyboardHidden"
From the docs:
"However, your application should always be able to shutdown and restart with its previous state intact. Not only because there are other configuration changes that you cannot prevent from restarting your application but also in order to handle events such as when the user receives an incoming phone call and then returns to your application."
JAL
Android does not handle that kind of stuff for you. You have save all data manually.
You can use in a activity to save values
#Override
public Object onRetainNonConfigurationInstance() {
HashMap<String, Object> savedValues = new HashMap<String, Object>();
savedValues.put("someKey", someData);
return savedValues;
}
and use something like this in the oncreate method of a activity to load the saved objects
HashMap < String, Object> savedValues
= (HashMap<String, Object>)this.getLastNonConfigurationInstance();
you can also choose the disable orientation change for an activity
<activity android:name=".Activity" android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
Modify your activities in AndroidManifest.xml to override orientation change behavior by adding this to your activity/activities:
android:configChanges="orientation|keyboardHidden"
It should look somewhat like this:
<activity android:name=".activity.LoginActivity"
android:configChanges="orientation|keyboardHidden"
android:label="#string/app_name">
</activity>
Add these to AndroidManifest.xml
Put your Activity Name in the place of Activity_Name
<activity android:name="Activity_Name"
android:screenOrientation="sensor"
...
android:configChanges="orientation|keyboardHidden|screenSize">
This will work with value changing TextField also.
just add
android:configChanges="orientation|screenSize"
to your Activity in AndroidManifest.xml.
When configuration changes Android restarts your activity by default. To change this you should override onConfigurationChanged() method. Also, you should add android:configChanges to your manifest file.
You can read more here.
I also used
android:configChanges="orientation"
and it did not work.
But then I found a solution.
Verify if you have the following line correctly in your maniest:
<uses-sdk android:minSdkVersion="11" android:targetSdkVersion="11" />
make sure it does not read something like
<uses-sdk android`:minSdkVersion="11" android:targetSdkVersion="15" />`
I had it the second way in first place but when I corrected it state got preserved.
My tabbed app does not redisplay the view with an orientation change.
I added
android:configChanges="keyboardHidden|orientation"
to the main tab activity and to each activity in the manifest.
I added to each activity this method:
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.active_alt);
mColorLegendBtn = (Button) findViewById(R.id.colorbtn);
mStatusView = (TextView) findViewById(R.id.celltitle1);
TextView mStatusView1 = (TextView) findViewById(R.id.celltitle2);
mStatusView1.setText(mStatusView1.getText()+"testcase1");
mStatusView.setText(mStatusView.getText()+"testcase");
initUI();
}
public void initUI() {
l1 = (ListView) findViewById(R.id.ListView01);
EfficientAdapter efficientAdapter = new EfficientAdapter(mContext);
l1.setAdapter(null);
l1.setAdapter(efficientAdapter);
}
On launch, the tabs, list, button and textview are displayed correctly.
When I change the orientation in the emulator, only the tabs are displayed none of the other widgets, the screen is black.
What am I missing?
I had exactly this problem. After much trial and error, I eventually solved it by making a one-line change to the manifest.
The trick is to add
android:configChanges="orientation|keyboardHidden"
to your TabActivity's entry in the manifest. Leave all the child activities alone. Don't even bother implementing onConfigurationChanged(), not even in the TabActivity.
I don't know how or why this seems to work, but the effect is the layout is refreshed, and both the tabs and the child activity content are redrawn correctly in the new orientation.
With success I found that the best way to have screen changes with most control is to make your layout xml for landscape mode in a seperate xml like so:
res/layout-land/youractivity.xml
using /layout/ and /layout-land/ for your layouts as well as Graham Borland answer is golden.
<activity android:name=".MainActivity"
android:label="#string/app_name"
android:screenOrientation="unspecified"
android:launchMode="standard"
android:configChanges="orientation|keyboardHidden"
>
the above snippet is what made mine work. :)
ohh I do believe the "unspecified" is what allows the system to do what it thinks is best...
Good luck!
In Mono for Android with a target API greater then 13 I found that the line which would go inside the namespace but outside the Activity class:
[Activity (Label = "Viewer", ConfigurationChanges = ConfigChanges.Orientation|ConfigChanges.ScreenSize)]
lead to the triggering of OnConfigurationChanged() even though changing the manifest had not.
Could it just be that your layout doesn't work in the landscape/portrait mode? Try starting you app after rotating, check if that gives the same results. If so: fix your layout :D