Screen auto rotates when unlocking - android

Hi I am trying to save some values in my activity but I'm having a problem when I save it with onSaveInstanceState and restore with onRestoreInstanceState, I am saving an int years and it saves the first time the screen changes orientation, the spinner repopulates and sets it at the last value , but not when I switch back the orientation again.
My orientation is set to landscape in my manifest, and I have the two save and restore method overridden but it doesn't seem to work, do I need to do something in onPause aswell?
here is my code:
int years;//global variable
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Spinner spinnerYears = (Spinner) findViewById(R.id.spinYears);//Spinner
final ArrayAdapter <Integer> adapter = new ArrayAdapter <Integer>(this,android.R.layout.simple_spinner_item );
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
for(int i=0;i<=100;i++)
{
adapter.add(i);
}
spinnerYears.setAdapter(adapter);
years = spinnerYears.getSelectedItemPosition();
}//onCreate
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putInt("MyInt", years);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Spinner spinnerYears = (Spinner) findViewById(R.id.spinYears);//Spinner
final ArrayAdapter <Integer> adapter = new ArrayAdapter <Integer> (this, android.R.layout.simple_spinner_item );
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
for(int i=0;i<=100;i++)
{
adapter.add(i);
}
spinnerYears.setAdapter(adapter);
TextView tvYears = (TextView) findViewById(R.id.tvYears);//spinner Tv
tvYears.setVisibility(TextView.GONE);
int myInt = savedInstanceState.getInt("MyInt");
spinnerYears.setSelection(myInt);//
Toast.makeText(getBaseContext(), "Restored int"+myInt, Toast.LENGTH_LONG).show();
}

Because you don't handle the event of changing orientation, so everytime you change orientation, your program (or Activity) is re-created, which means the onCreate() method is called always; which leads to a result that onSaveInstanceState() and onRestoreInstanceState() never being called.
It's being explained here in Android Documentation: http://developer.android.com/reference/android/app/Activity.html#ConfigurationChanges
In order to fix this, in AndroidManifest.xml , adding this attribute:
android:configChanges="orientation"
to avoid Activity restarted and, well, good luck with that!

In onRestoreInstanceState(), you never assign the value back the the variable years. You assign it to an int and then disregard it. So when onSaveInstanceState() is called, years hasn't been set yet and it saves that unset value (0).
If you change your getInt() line towards the bottom to be:
years = savedInstanceState.getInt("MyInt");
spinnerYears.setSelection(years);
it should start working. Good Luck!

Related

Spinner not clearing

I have a weird bug which I'm not sure why it's happening,
I have 2 activities: activity A and activity B.
When the app starts, it initializes a spinner once. I go to the second activity and then go back <-
onRestart() of the Activity A will be called. My problem is that even though I clear my spinner and reinitialize it in onRestart() it keeps reading the values.
For example, if spinner has 1/2 when you go to activity B then back to activity A, spinner has = 1/2/1/2.
I find this weird because when I just set the spinner adapter to null and comment out my initialize of spinner when I go back to activity A from activity B, my spinner is empty.
here is my code:
#Override public void onRestart() {
super.onRestart();
Spinner location = findViewById(R.id.spinnerLocation);
location.setAdapter(null);
initSpinner();// if this is commented out spinner is cleared, if not commented the same valus are added again
}
here is code for initSpinner(reads from shared prefs) this is not the problem
public void initSpinner(){
Spinner location = findViewById(R.id.spinnerLocation);
location.setAdapter(null);
SharedPreferences prefs = this.getSharedPreferences("Locations", Context.MODE_PRIVATE); //preffilename
SharedPreferences.Editor editor = prefs.edit();
editor.putString("1","St. Catharines");
editor.putString("2","Toronto");
editor.putString("3","Niagara Falls");
editor.commit();
int s = prefs.getAll().size();
for(int f=0;f<25;f++) {
if (prefs.getString(String.valueOf(f + 1), null) != null) {
DefaultLocations.add(prefs.getString(String.valueOf(f + 1), null));
}
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, DefaultLocations);
//set the spinners adapter to the previously created one.
location.setAdapter(adapter);
}
do
DefaultLocations.clear() before for loop inside initSpinner() method it may not clear when u adding new values

How to handle Spinners when screen orientation changes?

I have two Spinners. In onCreate i setup listeners for them. At some other places i populate them.
Now I am not sure what the best practice is for handling these spinners when screen orientation changes. Should i store all values and selected item in sharedPreferences somehow or in savedInstanceState?
If you can, please advise me in a prefered way and also include some sample code for handling spinners. The goal here is to keep the values and selected item thru the lifecycle.
I will include code at request or if needed.
Thanks
Try this, onSaveInstanceState for Screen Orientation for saving your selected value of spinner,According to my choice shared preference is not good choice for saving selected values of spinner.
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("mySpinner", mySpinner.getSelectedItemPosition());
// do this for each or your Spinner
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// initialize all your visual fields
if (savedInstanceState != null) {
mySpinner.setSelection(savedInstanceState.getInt("mySpinner", 0));
// do this for each of your text views
}
}
Add android:configChanges="orientation|screenSize" in your AndroidManifest file, it will keep spinner value selected on orientation change.
User Spinner Like this:
mSpinner = findViewById(R.id.spinner);
ArrayList<String> stringArrayList = new ArrayList<>();
for (int i = 0; i < 6; i++) {
stringArrayList.add("List Item " + i);
}
ArrayAdapter arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, stringArrayList);
spinner.setAdapter(arrayAdapter);

How to disable onItemSelected on Spinner for the first time when orientation changes happens?

I have an Activity with a Spinner. This Activity will load information from the internet based on the Spinner selection and show it in this Activity. When the first time the Activity is launched, the Spinner will be selected by default. I use Spinner#setOnItemSelectedListener so that each time the Spinner is selected, a method which will load information from the internet will be triggered.
#Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
String option = (String) parent.getItemAtPosition(pos);
loadInfoFromInternet(option);
}
When the orientation of the phone is changed, the Activity will be destroyed and recreated. I've stored the Spinner information and also the information I got from the internet in the savedInstanceState's bundle. With it, I managed to save the state of the Spinner and the info from internet.
The problem is with the info I got from the internet. When the orientation changes, Spinner will be recreated and select an option. This will trigger OnItemSelectedListener which will call onItemSelected. The loadInfoFromInternet will be triggered again. It makes my data which I stored in savedInstanceState be replaced.
What I want is when the orientation changes, I want the Spinner not to trigger loadInfoFromInternet so that I can show the information from previous state instead of loading from internet again.
Initially, I come up with the following idea:
private boolean isNewState = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
if (savedInstanceState == null) {
isNewState = true;
}
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
String option = (String) parent.getItemAtPosition(pos);
if (isNewState) {
loadInfoFromInternet(option);
}
}
With the above solution, when the orientation changes, the information is not loaded from the internet again. That's what I want, but, when I select another option, the loadInfoFromInternet will not be triggered since it's not a new state (isNewState = false). This is not what I want.
What you described in your question sounds on track. Inside your onCreate() method you can check the Bundle parameter which gets passed in. If the bundle is not null, then you can assume that you have saved state for your spinner and you can load that state.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ...
if (savedInstanceState == null) {
isNewState = true;
}
else {
int sIndex = savedInstanceState.getInt("S_INDEX");
Spinner spinner = (Spinner) findViewById(R.id.yourSpinner);
spinner.setSelection(S_INDEX);
}
}
and add logic to onSaveInstanceState() to save the index state of the spinner:
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
Spinner spinner = (Spinner) findViewById(R.id.yourSpinner);
int sIndex = spinner.getSelectedItemPosition();
savedInstanceState.putInt("S_INDEX", sIndex);
}
Note that onSaveInstanceState() will get called each time your phone changes orientation. All you need to do is store the state of the activity in the Bundle to persist it across changes.

Restore Android GridView after screen orientation change (without reloading it)

I'm new to Android (this is my first application) and I made a GridView in an Activity which I'd like it to be responsive according to screen position (portrait / landscape). Of course I made some custom layout values of GridView rows width for portrait as well as for landscape, and it works perfectly.
Except that, on every screen orientation change, the GridView is reloading again. And that's not good for user experience. I only like the GridView (and definitely its rows) to adjust to new screen width without doing all the onCreate() instructions (retrieving GridView's data from internet, assigning retrieved data in a HashMap object, setting the GridView's Adapter, then display the GridView's rows).
I went through many forum threads and some Google documentation that talk about restoring simple values, but never found an answer for restoring a GridView without having it to reload again.
I read about onSaveInstanceState() and onRestoreInstanceState(), but I didn't know how to use them in my case (GridView case).
Could any one provide a simple code sample for this? Or at least some headlines to follow?
Here's some of what I tried in my code, in the Activity class :
private Parcelable mListInstanceState;
private Parcelable mAdapterInstanceState;
private GridView gridView = null;
private MyAdapter myAdapter = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gridView = (GridView) findViewById(R.id.gridview);
// Check whether we're recreating a previously destroyed instance
if(savedInstanceState != null) {
// Restore value of members from saved state
mListInstanceState = savedInstanceState.getParcelable("gridview");
mAdapterInstanceState = savedInstanceState.getParcelable("adapter");
}
else {
// Retrieve data from internet, fill HashMap object,
// set Adapter and display GridView only for the first time the activity is created
attemptToDisplayGirdViewItems();
}
}
#Override
protected void onSaveInstanceState(Bundle state) {
// Save activity state
super.onSaveInstanceState(state);
state.putParcelable("gridview", gridView.onSaveInstanceState());
// state.putParcelable("adapter", myAdapter);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
// Retrieve and restore activity state
// Restore state members from saved instance
mListInstanceState = savedInstanceState.getParcelable("gridview");
mAdapterInstanceState = savedInstanceState.getParcelable("adapter");
super.onRestoreInstanceState(savedInstanceState);
}
You don't need to save the views. If they have ID, they'll be saved automatically (such as scroll position of a GridView). What you need to save is the adapter's data set.
Your adapter presumably holds a list of items. Unless these items are primitives or String or implement Serializable, they need to implement Parcelable for this to work.
See here how to do that: How can I make my custom objects Parcelable?
Your adapter needs a getItems method which returns the data set - an ArrayList of your parcelable items. It also needs to have a setItems(...) method or a constructor taking a list of items as parameter.
Then your activity will look like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gridView = (GridView) findViewById(R.id.gridview);
myAdapter = new MyAdapter(); // Create empty adapter.
if(savedInstanceState != null) {
ArrayList<MyItem> items = savedInstanceState.getParcelableArrayList("myAdapter");
myAdapter.setItems(items); // Load saved data if any.
}
gridView.setAdapter(myAdapter);
}
#Override
protected void onSaveInstanceState(Bundle state) {
super.onSaveInstanceState(state);
state.putParcelableArrayList("myAdapter", myAdapter.getItems());
}

Spinner resets value after onActivityResult

I have a Spinner with a bunch of state names. In onCreate, I set it to a default value. The index 0 in the Spinner array is "Alabama"
String state = "California"; //preset to this
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_state_and_drivers_license);
statesSpinner = (Spinner)findViewById(R.id.states_spinner);
adapter = (ArrayAdapter<String>)statesSpinner.getAdapter();
statesSpinner.setSelection(adapter.getPosition(state));
startActivityForResult(cameraIntent, RESULT_CAMERA);
}
However, after onResult, the Spinner is once again set to "Alabama". Meaning it reverts back to index 0 of the array, even though I thought it should keep its existing selected value.
Try relocating this in the onResume call.
Also use logcat to see if onCreate is being called.

Categories

Resources