Button text gets reset on orientation change - android

In my android app, I am trying to solve an issue with orientation change.
I have a main layout where I have two buttons. On click of the first button (default text on this button is "Select a category"), a dialog box appears with a category list with categories displayed as radio buttons. After the user selects a category, the selected category name appears on the button. Now when I change the orientation in the emulator, the Button text gets reset again.
I have used onSaveInstanceState() like below.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Initialization code
categoryList=(Button)findViewById(R.id.category_selection);
if (savedInstanceState != null)
{
System.out.println("savedInstanceState---
"+savedInstanceState.getString("bundle_category_name"));
categoryName=savedInstanceState.getString("bundle_category_name");
categoryList.setText(categoryName);
}
else
{
categoryList.setText(R.string.category);
}
// remaining code
}
#Override
public void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
// Save selected category name
System.out.println("saving category name "+categoryName);
outState.putString("bundle_category_name", categoryName);
}
I am able to get the category name back in onCreate(), the sysout prints correctly. But it is not getting set as the button text after change in orientation.
Please let me know if I am doing anything wrong.
Thanks

Add android:configChanges="orientation|screenSize" in your Android Manifest file.
<activity android:name="YourActivity"
...
android:configChanges="orientation|screenSize"
.../>

Saving and restoring the data works using two Activity lifecycle methods called onSaveInstanceState() and onRestoreInstanceState().
To save the state information override onSaveInstanceState() method and add key-value pairs to the Bundle object that is saved in the event that your activity is destroyed unexpectedly. This method gets called before onStop().
To recover your saved state from the Bundle override onRestoreInstanceState() method. This is called after onStart() and before onResume(). Check the below code
public class MainActivity extends Activity{
private static final String SELECTED_ITEM_POSITION = "ItemPosition";
private int mPosition;
#Override
protected void onSaveInstanceState(final Bundle outState) {
super.onSaveInstanceState(outState);
// Save the state of item position
outState.putInt(SELECTED_ITEM_POSITION, mPosition);
}
#Override
protected void onRestoreInstanceState(final Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Read the state of item position
mPosition = savedInstanceState.gettInt(SELECTED_ITEM_POSITION);
}
}

#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
// Save UI state changes to the savedInstanceState.
// This bundle will be passed to onCreate if the process is
// killed and restarted.
savedInstanceState.putBoolean("MyBoolean", true);
savedInstanceState.putDouble("myDouble", 1.9);
savedInstanceState.putInt("MyInt", 1);
savedInstanceState.putString("MyString", "back to Android");
// etc.
}
To Retrieve the data
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore UI state from the savedInstanceState.
// This bundle has also been passed to onCreate.
boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
double myDouble = savedInstanceState.getDouble("myDouble");
int myInt = savedInstanceState.getInt("MyInt");
String myString = savedInstanceState.getString("MyString");
}

Related

Have Activity A and B in activity

I Have Activity A and B. In activity A , I load data then when click on the list it move me to activity B. When go back to activity A the data load again. How to prevent this ?
When you move from one activity to another, say from activity A to activity B, then the data which you have loaded gets lost. To prevent the data reloading, you need to override onSaveInstanceState(Bundle savedInstance).
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
// Save UI state changes to the savedInstanceState.
// This bundle will be passed to onCreate if the process is
// killed and restarted.
savedInstanceState.putBoolean("MyBoolean", true);
savedInstanceState.putDouble("myDouble", 1.9);
savedInstanceState.putInt("MyInt", 1);
savedInstanceState.putString("MyString", "Welcome back to Android");
// etc.
}
And you can extract those values by overriding onRestoreInstanceState(Bundle savedInstance).
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore UI state from the savedInstanceState.
// This bundle has also been passed to onCreate.
boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
double myDouble = savedInstanceState.getDouble("myDouble");
int myInt = savedInstanceState.getInt("MyInt");
String myString = savedInstanceState.getString("MyString");
}
Also you can store and retrieve the arraylist.

Going back and forth between intents without losing user entered data

I have a form. Here, the user fills in details like event name, description, location etc. To select the location, I have set a button. This is my button code:
btnMap.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent map = new Intent(getApplicationContext(), Map2.class);
startActivity(map);
}
});
I select the location from there, and the data is passed back to my main intent correctly. But the thing is, the data in the other fields like event, description etc. that users filled in are lost.
I tried startActivityForResult(map,1); too. Doesn't work. Is there a way to keep the data, without sending them in a bundle to the other intent and getting them back? like the select image button does? It goes to the gallery and comes back without resetting the other fields
contactImageImgView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Image"), 1);
}
});
You need to save your activity state.
Override the method onSaveInstanceState and persist all your data in the bundle
In onCreate, if savedInstanceState is not null, restore all your data and set all the fields.
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putInt("MY_FIELD", 43);
// ... other fields
super.onSaveInstanceState(savedInstanceState);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
if (savedInstanceState != null) {
int value = savedInstanceState.getInt("MY_FIELD");
// ... update your views
} else {
// no previous state, start fresh
}
}
Details here
Note: you have mentioned that rotation is blocked. This is generally bad for the user unless it's part of the feature of the app.
Explanation:
A screen rotation is a configuration change that causes the activity to restart with the appropriate resources. There are many more configuration changes such as screen unlock,device docked etc. Not all of them trigger an activity restart but some do. When your activity restarts due to a configuration change, onSaveInstanceState gets called and savedInstanceState will be not-null when onCreate is called.
When you start a new activity Android may destroy the previous one to recover some of the resources it was consuming. In that case, when you return to that previous activity, it is actually a new instance of the Activity subclass and the internal state has been lost. It's up to you to save and restore any state necessary within the onSaveInstanceState and onCreate callback methods, respectively.
Have a look at this page for more information and examples: Recreating an Activity | Android Developers
public class FormActivity extends Activity {
private static final String NAME = "NAME";
private EditText nameEdit;
// Declare other view references here...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_form);
nameEdit = (EditText) findViewById(R.id.name_edit);
// Find other views...
if (savedInstanceState != null) {
final String nameValue = savedInstanceState.getString(NAME, "");
nameEdit.setText(nameValue);
// Restore other saved values...
} else {
// No saved values to restore
}
}
#Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
final String nameValue = nameEdit.getText().toString()
outState.putString(NAME, nameValue);
// Put (save) other values into the outState bundle...
super.onSaveInstanceState(outState, outPersistentState);
}
// Other FormActivity code...
}

edit text saving status in android

i did a lot of trials before coming here, i need that user find the same values entered in
an activity when he returns to , i did this code but it is not working :
public class ActivityUn extends Activity {
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putString("arm_1", rm_1ts);
savedInstanceState.putString("arm_2", rm_2ts);
super.onSaveInstanceState(savedInstanceState);
}
public void ajouter(View v) {
db.open();
long id = db.insertMENAGE(rm_1ts,rm_2ts); }
EditText rm_1;
EditText rm_2;
String rm_1ts = "";
String rm_2ts = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_un);
rm_1 = (EditText)findViewById(R.id.rm_1);
rm_2 = (EditText)findViewById(R.id.rm_2);
if (savedInstanceState != null) {
// Restore value of members from saved state
rm_1ts = savedInstanceState.getString("arm_1");
rm_2ts = savedInstanceState.getString("arm_2");
rm_1.setText(rm_1ts);
rm_2.setText(rm_2ts);
}
Button bton = (Button)findViewById(R.id.ajoutUn);
bton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
rm_1ts = rm_1.getText().toString();
rm_2ts = rm_2.getText().toString();
ajouter(v);
}
});
The problem is that onSaveInstanceState is only called when your Activity is killed via System to free memory or a 3rd party app. But when you press a back button in an Activity it simply is equivalent to finish(). In this case onSaveInstanceState is not called. So if you want to store data every time your Activity is created just store the values in a SharedPreference. You can store the values either in onStop or onPause method depending on your needs.
Here you can learn more about SharedPrefence and other types of storage options.
For the sake of simplicity, you could store the value in the SharedPreferences.
getSharedPreferences().edit().putString("myEditText", yourValue).commit();
That's it.
Try restoring the state in onStart or onResume instead of onCreate. onCreate is only called if the activity needs to be recreated after it is destroyed. Often the activity will be retained in the background in a stopped state, and won't call onCreate when it comes back.
Anywhere in your file, put:
#Override
public void onResume() {
super.onResume();
//Your code here
}

Save state of TextView and Spinner inside of CustomView

I have 3 custom views.
The first one works great. It contains an EditText when I launch an intent and come back whatever the user entered is restored.
The 2nd contains a TextView and the 3rd a Spinner. They do not save when I launch my intent and return.
I think know how to preserve the data using onSaveInstanceState and onRestoreInstanceState in my custom views, However when the activity containing the custom views is not killed (meaning it is only paused), and I return onRestoreInstanceState is not called.
This is what I'm calling in my custom views when I need to save them.
#Override
public Parcelable onSaveInstanceState() {
textValue = editText.getText().toString();
Bundle bundle = new Bundle();
bundle.putParcelable("instanceState", super.onSaveInstanceState());
bundle.putString(TEXT_VALUE_KEY, this.textValue);
return bundle;
}
#Override
public void onRestoreInstanceState(Parcelable state) {
if (state instanceof Bundle) {
Bundle bundle = (Bundle) state;
textValue = bundle.getString(TEXT_VALUE_KEY);
editText.setText(textValue);
super.onRestoreInstanceState(bundle.getParcelable("instanceState"));
return;
}
super.onRestoreInstanceState(state);
}
I'm unsure I what I should do since onRestoreInstanceState is not called. I think the EditText customView works because default android behavior saved them temporarily, but it doesn't save spinners or TextViews.
You should change your onCreate() method in order to check if the Activity has already called onSavedInstanceState like this:
#Override
public void onCreate(Bundle savedInstanceState) {
if(savedInstanceState == null) {
// The activity haven't called onSavedInstanceState(), which means you should initialize your objects and UI here
}
else {
// Whatever states you saved onSavedInstanceState() are stored in savedInstaceState, so use them to reconstruct your customViews
}
}

Not able to restore saved instance of activity

Here is my GamePlay Activity code
public class GamePlay extends Activity implements OnClickListener {
private boolean disableSound = false;
//.....
//Code Code
//.....
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//.....
//Code Code
//.....
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
// Save UI state changes to the savedInstanceState.
// This bundle will be passed to onCreate if the process is
// killed and restarted.
savedInstanceState.putBoolean("disableSound", disableSound);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore UI state from the savedInstanceState.
// This bundle has also been passed to onCreate.
disableSound = savedInstanceState.getBoolean("disableSound");
Menu menu = (Menu)findViewById(R.menu.tic_tac_toe);
MenuItem toggleSoundItemMenu = menu.findItem(R.id.toogle_sound_menu);
if(disableSound)
toggleSoundItemMenu.setTitle(R.string.toggle_sound_off_label);
else
toggleSoundItemMenu.setTitle(R.string.toggle_sound_on_label);
}
//other functions and code
}
Now on game restart I am restarting the activity. Following code is inside the onClickListener() withing appropriate case
case R.id.game_play_restart_button:
Intent restartActivity = new Intent(this,GamePlay.class);
finish();
startActivity(restartActivity);
break;
But still the state does not persist. I disable the sound and restart the game then sound turns back on which is the default behavior. What am I missing? Any suggestion is appreciated.
The savedInstanceState bundle is kept by the system as long as the activity hasn't been destroyed by the system.
When you call finish, you destroy the current activity, and the bundle that comes with it.
That's the reason why you can't get your boolean back.
You should consider passing this boolean as an extra in the intent like:
restartActivity.putExtra("disableSound", disableSound)
And then on the onCreate of your activity:
getIntent().getBooleanExtra("disableSound", false)
Please note that the last parameter false is just a default value. You can set it to true if that's the behaviour you want.

Categories

Resources