I make a login form with dynamic field validation. I have 3 fields username, email & password & all of these field are required. When field length = 0, I set error
editText.setError( getText(R.string.cannot_be_blank) );
and this code works fine, but when I change the orientation, all the errors disappear
How to save error state?
Thanks.
When the orientation is changed the framework will recreate the Activity by calling onCreate(Bundle savedInstanceState). Before the switch in orientation the onSaveInstanceState(Bundle outState) method will be called if it is overridden in your Activity.
You can save the state of your errors in the Bundle passed into the onSaveInstanceState method. This bundle is passed to your onCreate() method as the savedInstanceState Bundle.
Therefore you need to override the onSaveInstanceState method in your Activity as follows (saving the state of your errors):
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putBoolean("errorOccurred", errorState);
super.onSaveInstanceState(outState);
}
Then in your onCreate method check if the savedInstateState Bundle is null or not. If not, you can retrieve the values out of it with the following code:
boolean errorOccurred = false;
if (savedInstanceState != null) {
errorOccurred = savedInstanceState.getBoolean("errorOccurred");
}
When the orientation is changed the Android framework destroys the Activity and then creates a new one for the new orientation. So all your state is lost.
Use SharedPreferences to store and restore your state and TextEdit values.
What happens when you turn the device is that your Activity runs through its lifecycle in order to deal with the fact that the layout must change from portrait to landscape.
You should take a look at the developer docs on how to Handle Runtime Changes.
Related
I've got an Android application which maintains state regarding distance traveled, time elapsed, etc. This state I can conveniently store in an object and store a reference to that object in the Bundle when Android calls onDestroy() when the user changes the screen orientation, then restore the state in onCreate(Bundle savedBundle). However, I also have some state in the Buttons and EditText objects on the screen that I want to persist through screen orientations. For example, in onStart(Bundle savedBundle) I call:
_timerButton.setBackgroundColor(Color.GREEN);
_pauseButton.setBackgroundColor(Color.YELLOW);
_pauseButton.setEnabled(false);
Then throughout the operation of my app, the colors/enabled status of these buttons will be changed. Is there a more convenient way to persist the state of user interface items (EditText, Button objects, etc) without having to manually save/restore each attribute for each button? It feels really clumsy to have to manually manage this type of state in between screen orientations.
Thanks for any help.
Add android:configChanges in the Manifest file
<activity name= ".MainActivity"
android:configChanges="orientation|screenSize"/>
By default, this does not work because changing the orientation causes the onCreate method to be called again and redraws the view.
However, if this parameter is included, the framework will handle preserving the state of the screen or layout if the orientation is changed.
Refer following official documentation for more info:
Activity Lifecycle
Handling configuration changes
To save your variable or values you should use onSaveInstanceState(Bundle); and when orientation changes then should recover values should use onRestoreInstanceState() as well, but not very common. (onRestoreInstanceState() is called after onStart(), whereas onCreate() is called before onStart().
Use the put methods to store values in onSaveInstanceState()
protected void onSaveInstanceState(Bundle icicle) {
super.onSaveInstanceState(icicle);
icicle.putLong("param", value);
}
And restore the values in onCreate():
public void onCreate(Bundle icicle) {
if (icicle != null){
value = icicle.getLong("param");
}
}
I have a fragment with an EditText in it, where users can enter a longer text. Now when users type something, turn the screen off for whatever reason, and then turn the screen on again the EditText is empty.
I thought that onSaveInstance should be the right place to save the state, and any of the create methods (that actually have the saveInstance parameter) should be enough to retrieve the previously saved state - but it's not working. onSaveInstance is called, but the create methods do not retrieve this object.
So the question:
How can I save my fragment's state when screens turn off, and how can I restore this state when the screen is turned on again?
Edit:
I have implemented blackbelt's approach, but it's still not working. (savedInstanceState is null)
#Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
review.finalStatement = savedInstanceState.getString
(BUNDLE_KEY_STATEMENT);
}
}
#Override
public void onSaveInstanceState(final Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(BUNDLE_KEY_STATEMENT, review.finalStatement);
}
I have a fragment with an EditText in it, where users can enter a
longer text. Now when users type something, turn the screen off for
whatever reason, and then turn the screen on again the EditText is
empty.
It is not the default behaviour. EditText states should be kept as it was.
I thought that onSaveInstance should be the right place to save the
state, and any of the create methods (that actually have the
saveInstance parameter) should be enough to retrieve the previously
saved state - but it's not working. onSaveInstance is called, but the
create methods do not retrieve this object.
It is. You should use the pair onSavedInstanceState/onActivityCreated and not onCreate
In my app, I use the onCreate() method to initialize various variables. However, whenever I rotate the device, and the screen auto-rotates, onCreate() is called again, which re-initialize my variables. Is that how it's supposed to work? Where should I put code that I only want to be run once, when I start the app?
The above answers will lock your Activity into a specific orientation, which is generally not proper behavior for an Android app.
What you should be doing is storing your activity's state so when it gets recreated you can repopulate the UI with the stored values.
protected void onSaveInstanceState (Bundle outState) {
super.onSaveInstanceState(outState);
// put your values in the Bundle
outState.putString("TextView1Text", textView1.getText()); // for example;
}
Then in your onCreate() method you can restore the values
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
textView.setText(savedInstanceState.getString("TextView1Text"));
}
}
This will also work when the user leaves the app via the home button or other means.
In the manifest put this line in all the activities that you want PORTRAIT
android:screenOrientation="portrait"
I am working on android apps. My app should work both in portrait and landscape mode. I adjusted all the layouts by keeping all layout files in layout-lan folder. But now my issue is with functionality i.e when the app is changed to landscape mode the values of my parameters are changing and due to this I am getting crashes. i.e i kept a counter value but it is displaying wrong count value when turned to port-lan. Also the functionality is changing due to this.
Please help me in this regard.
Each time you rotate the devide, onCreate method is being called again. You can save the values by overriding onSavedInstanceState and get them back in onRestoreInstanceState or in onCreate method. For example:
save the value:
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean("booleanValue", true);
}
restore the value (you can call this in onCreate as well):
protected void onRestoreInstanceState(Bundle savedInstanceState) {
if (savedInstanceState != null && savedInstanceState.containsKey("booleanValue")) {
boolean myBoolean = savedInstanceState.getBoolean("booleanValue");
}
super.onRestoreInstanceState(savedInstanceState);
}
Your activity restarts every time the orientation changes.
You have to store your values in onSaveInstanceState and restore them in onRestoreInstanceState. You will find the details here: http://developer.android.com/guide/topics/resources/runtime-changes.html
those values change because the activity gets destroyed and re-built during rotation,
please check the developers guide on how to save your activity state.
http://developer.android.com/training/basics/activity-lifecycle/recreating.html#SaveState
According to the documentation of onSaveInstanceState:
The default implementation takes care of most of the UI per-instance state
and onRestoreInstanceState:
The default implementation of this method performs a restore of any view state that had previously been frozen
I'm not sure exactly what that means.
Is it meant to mean that when returning after being killed and now restored, that the UI screen shown to the user is automatically restored with all its data?
If so, I am not seeing that.
All I get is an empty screen unless I do setContentView myself.
AM I misunderstanding the meaning?
Default implementation will work for every widget which ids are defined.
For example, If you have one EditText and if you will provide its id then system will save its value when Activity will be killed due to orientation and same and it will restore the EditText value when activity will be re-created.
Edit
If you have one base layout and if you are dynamically adding some views in the view hierarchy then you will have to handle the save state and restore state your self. also when your activity will be re-created then onCreate() method of the activity will be called so in this method first set all the addition views which you are creating and adding dynamically and then you can check the extra parameters with the intent which you are getting in the onCreate() method. This extra parameters are exactly same as you have adding extra parameters in the onSaveInstanceState method.
So implement like below.
int x = 10;
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("x", x);
}
And in onCreate method you can get this x parameters like below
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xxx);
if(savedInstanceState.containsKey("x")) {
x = savedInstanceState.getInt("x");
}
}