I am trying to create a basic application that just counts how many times the user changes the orientation to landscape from portrait and displays the count on screen. I have:
public class MainActivity extends Activity {
int count = 0;
private static boolean inLandscape = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.count);
tv.setText(getResources().getString(R.string.count) + ' ' + count);
if (!inLandscape && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)
{
inLandscape = true;
count++;
Log.e("Debug","In Landscape " + count);
}
else if (inLandscape && getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
inLandscape = false;
}
The problem is, in my debug statement count is always 1, and the text never changes on the screen. Doing some research, I think this is because the activity gets trashed and recreated every time the orientation changes. How do I maintain the variable value throughout orientation change?
I tried using the savedInstanceState with
if (savedInstanceState.containsKey("count"))
count = savedInstanceState.getInt("count");
savedInstanceState.putInt("count", count);
but this gives a NullPointerException at the containsKey line.
Override onSaveInstanceState to store your orientation change counter.
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putInt("count", count)
}
and override onRestoreInstanceState to read it back after a change.
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
count = savedInstanceState.getInt("count");
}
Obviously, you can still keep your code in the same place in 'onCreate', for conditionally adding to the counter depending on the orientation each time onCreate is called.
It's giving you a NullPointerException because saveInstanceState is null. You also need to put the savedInstanceState.putInt("count", count) inside your onRestoreInstanceState method. So your code would look like...
int mCount;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.count);
mCount = 0;
tv.setText(getResources().getString(R.string.count) + ' ' + mCount);
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mCount++;
tv.setText(getResources().getString(R.string.count) + ' ' + count);
}
public void onRestoreInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState);
mCount = savedInstanceState.getInt("count");
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putInt("count", mCount);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
Please see http://developer.android.com/training/basics/activity-lifecycle/recreating.html and http://developer.android.com/guide/topics/resources/runtime-changes.html for more information.
Related
Saving the State of Drawable xml Button.
private boolean mJam;
private button mSwitch;
private static final String KEY_ENABLE = "KEY_ENABLE";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if( null == savedInstanceState ) {
mJam = false;
} else {
mJam = savedInstanceState.getBoolean(KEY_ENABLE);
}
button_layout();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putBoolean(KEY_ENABLE, mJam);
outState.putBoolean(KEY_ENABLE, mSwitch.isSelected()); // Saving the state of the
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
mSwitch.setSelected(savedInstanceState.getBoolean(KEY_ENABLE));
mJam = savedInstanceState.getBoolean(KEY_ENABLE);
super.onRestoreInstanceState(savedInstanceState);
}
Note: If you don't want to use ScreenSize in Android manifest, This code can be used,
If you want to do it Manually, then go for this one.
P.S: setting Screen Size in Manifest, never go to onCreate if the Orientation Change, It Just saved all the instance and display as it is, when
Android orientation Change.
When I change to landscape mode I want to save informations, I wrote this code, but when I start the program it shows ResourceNotFoundException, why?
public class ActivityB extends AppCompatActivity {
int value = 0;
TextView text;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_activity_b);
text = (TextView) findViewById(R.id.textView);
Button b = (Button) findViewById(R.id.button);
//Toast.makeText(this," svd : "+savedInstanceState,Toast.LENGTH_LONG).show();
if (savedInstanceState != null) {
value = savedInstanceState.getInt("count");
text.setText("" + value); // here is the Error! why ?
}
}
public void Incrementation(View view) {
value++;
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("count", value);
}
}
LOG
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.othma.udemy/com.example.othma.udemy.ActivityB}: android.content.res.Resources$NotFoundException: String resource ID #0x6*
First, you need to handle your logic in onCreate properly.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_activity_b);
text = (TextView) findViewById(R.id.textView);
Button b = (Button) findViewById(R.id.button);
//Toast.makeText(this," svd : "+savedInstanceState,Toast.LENGTH_LONG).show();
if (savedInstanceState != null) {
value = savedInstanceState.getInt("count"); // here where we retrieve back the value
} else {
text.setText("" + value); //first time init savedInstanceState will be null
}
}
I think you need to reorder this also.
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt("count", value); // used to store data before pausing the activity.
super.onSaveInstanceState(outState);
}
Hope that helps!
I want to keep the spinner position when the screen is rotated
I've looked at a few answers on here and so far have the following
Aim - Store the position of the spinner
protected void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
flav1Spinner = (Spinner)findViewById(R.id.Combo_InvChoice1);
Integer flav1 = flav1Spinner.getSelectedItemPosition();
savedInstanceState.putInt("cho1", flav1);
}
Aim - Restore position
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calculation);
Locale.setDefault(Locale.US);
if (savedInstanceState != null){
flav1Spinner = (Spinner)findViewById(R.id.Combo_InvChoice1);
Integer flav1 = savedInstanceState.getInt("cho1");
flav1Spinner.setSelection(flav1);
}
However while debugging I can see that the Integer Flav1 is getting a value assigned to it and the digit is being retrieved, however the spinner isn't changing it's position. Any suggestions?
You can do it by onSaveInstanceState(), As below
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("yourSpinner", yourSpinner.getSelectedItemPosition());
// do this for each of your Spinner
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
yourSpinner.setSelection(savedInstanceState.getInt("yourSpinner", 0));
// do this for every text views
}
}
Check Saving Activity state, it will help you to get more details.
I'm struggling to recover my position in a listview on screen rotation configuration change.
Amongst the many things I've tried I came to this:
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState == null) {
...
mVisibleItem = -1;
} else {
if (savedInstanceState.containsKey(LV_VISIBLE_ITEM)) {
mVisibleItem = savedInstanceState.getInt(LV_VISIBLE_ITEM);
}
}
setRetainInstance(true);
}
and here I'm trying to set the position in the listview
#Override
public void onResume() {
super.onResume();
if (mVisibleItem > 0) {
mlvDictionaryIndex.setSelectionFromTop(mVisibleItem, 0);
}
}
However, much to my surprise, after rotating the screen and watching mVisibleItem gets set with the correct value, in onResume I see that mVisibleItem equals -1. How come?
use onSavedInstanceState to write in the bundle the returned value of ListView.onSaveInstanceState(), and restored it onActivityCreated
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mListView != null) {
outState.putParcelable(LISTVIEW_INTERNAL_STATE_KEY, mListView.onSaveInstanceState());
}
}
after the data are reload then you can call
mListView.onRestoreInstanceState(savedInstanceState.getParcelable(LISTVIEW_INTERNAL_STATE_KEY));
Override onSaveInstanceState such as below"
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putInt("pos", pos);
}
Then in your onCreate method have read the savedInstanceState to check if this is an orientation change or a new activity.
private int pos = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
//This is a new activity
}else{
pos = savedInstanceState.getInt("");
}
Now you have the position in the list, and you can scroll to this in configuration change.
Maybe after the data in the listview is reloaded,the code below will work.
mlvDictionaryIndex.setSelectionFromTop(mVisibleItem, 0);
So you can use post() method, just like below:
post(new Runnable() {
public void run() {
mlvDictionaryIndex.setSelectionFromTop(mVisibleItem, 0);
}
});
I need to clear error for EditText, when orientation screen change. I try in onStart() method set setError(null), but it doesn't work.
I tried it on the new project, but doesn't still work. Whem i click on button, field set error, when i change orientation i expect, that erro clear, but it doen't work.
public class MainActivity extends ActionBarActivity {
EditText text;
Button btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (EditText) findViewById(R.id.et);
btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
text.setError("Error");
}
});
}
#Override
public void onStart(){
super.onStart();
text.setError(null);
}
}
UPDATE:
It seems you have to clear errors onPause instead of onResume/onStart:
#Override
protected void onPause(){
super.onPause();
text.setError(null);
}
The above works for me.
OLD:
Android will automatically handle EditText for you, and its states, on orientation change.
If you want to handle the state yourself you need to implement and override onSaveInstanceState and not call super(). You don't need to override onRestoreInstanceState unless you need to handle restoring for other stuff.
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
//super.onSaveInstanceState(outState);
}
This is what I will do when orientation changes.
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
text.setError(null);
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
text.setText("Something");
}
}
And you can just the value of TextView as text.setText("") if you want to clear the "Error message" and if again the orientation changes, just set the text to anything you want.