0

My Android app has two Spinners (dropdown menus) working fine.

However, now I've added an OptionsMenu with:

  1. One submenu with options to open an AlertDialog textbox.
  2. One submenu with options to change language (locale).

If I click one option in the first submenu, the contents in both of my spinners get deleted, and then the textbox gets opened. When I click myself out of the textbox, the spinners are still cleared.

Similarly, if I click myself into changing language, both of the spinners get cleared, while the rest of the program gets updated to the new language. By restarting the app, all the contents are back.

If it matters, the spinners get their contents from an ArrayAdapter.

So I wonder, how can I update the spinners when they get cleared? I've tried "repopulating" the spinners with code in onCreate, onResume or onConfigurationChanged, but it didn't make any change.

I can find more code if you need, but at least here's some of it:

Spinner spinner1;
Spinner spinner2;
ArrayAdapter<CharSequence> adapter1;
ArrayAdapter<CharSequence> adapter2;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.setContentView(R.layout.main);

    spinner1 = (Spinner) findViewById(R.id.spinner1);
    adapter1 = ArrayAdapter.createFromResource(
            this, R.array.some_array, android.R.layout.simple_spinner_item);
    adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner1.setAdapter(adapter1);
    spinner1.setSelection(1);

    // Same procedure for spinner2...
    }


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    Resources res = getResources();
    SubMenu faqMenu = menu.addSubMenu(0, 100, 1, res.getString(R.string.FAQ)).setIcon(android.R.drawable.ic_menu_rotate);
        faqMenu.add(1, 101, 0, R.string.someText);
    SubMenu langMenu = menu.addSubMenu(0, 200, 2, res.getString(R.string.language)).setIcon(android.R.drawable.ic_menu_rotate);
        langMenu.add(1, 201, 0, "Language1");
        langMenu.add(1, 202, 0, "Language2");
        langMenu.add(1, 203, 0, "Language3");
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch(item.getItemId()){

    case 101:
        AlertDialog.Builder textbox = new AlertDialog.Builder(main.this);
        Resources res = getResources();
        textbox.setMessage(res.getString(R.string.someText));
        textbox.show();
        this.setContentView(R.layout.main);
        try{
            spinner1.setAdapter(adapter1);
            spinner2.setAdapter(adapter2);
            spinner1.setSelection(1);
            spinner2.setSelection(2);
        } catch (Exception e){
            e.printStackTrace();
        }
        break;

    case 201:

        Locale locale = new Locale("en"); 
        Locale.setDefault(locale);
        Configuration config = new Configuration();
        config.locale = locale;
        getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
        Toast.makeText(this, "Here is text in Language1! But unfortunately you need to restart the app before the spinners start working again...sorry!", Toast.LENGTH_LONG).show();
        this.setContentView(R.layout.main);
        try{
            spinner1.setAdapter(adapter1);
            spinner2.setAdapter(adapter2);
            spinner1.setSelection(1);
            spinner2.setSelection(2);
        } catch (Exception e){
            e.printStackTrace();
        }
        break;

    // Similar code for options 202, 203

    }
    return super.onOptionsItemSelected(item);
}

final Button button = (Button) findViewById(R.id.button1);
    button.setOnClickListener(new View.OnClickListener() {
        // Perform action on click
        public void onClick(View v) {
            // Make text box
            AlertDialog.Builder textbox = new AlertDialog.Builder(MyActivity.this);
            Resources res = getResources();

            // Get the chosen values from the spinners
            String spinner1choice = spinner1.getSelectedItem().toString();
            String spinner2choice = spinner2.getSelectedItem().toString();

            // Some code for showing the selected items.
     }
}

So...anyone got any help on how to update/refresh the spinners?

anderfo
  • 113
  • 1
  • 7
  • how do you set the spinner1.setAdapter(adapter1); back? when you call setAdapter() back? may be you should use onDestroy() of AlertDialog. you are calling this.setContentView(R.layout.main); when are you calling the setAdapter() – Sergey Benner Jan 31 '12 at 00:35
  • I call `spinner1.setAdapter(adapter1)` right after making the adapter (in the `onCreate()` method), but never again, in this code. But I've tried putting it other places in addition, it didn't help... I checked the API but couldn't find any `onDestroy()` method for the `AlertDialog` class. – anderfo Jan 31 '12 at 00:40
  • make the ArrayAdapter adapter1 private in global scope. then set it in onCreate(). then try to call `spinner1.setAdapter(adapter1)` right after `this.setContentView(R.layout.main);` in both of your cases. see if it will work. – Sergey Benner Jan 31 '12 at 00:45
  • thanks, i tried it, but it makes the activity crash.: "Unfortunately, yourActivity has stopped (OK)" – anderfo Jan 31 '12 at 02:06
  • what was your exception? move the spinners and adapter1 to the global scope right before the onCreate() method. the all should be visible to other methods and remove `final` keyword there. – Sergey Benner Jan 31 '12 at 02:22
  • aha, catching a `java.lang.nullPointerException`. but i'm not allowed to choose anything else than `final` (then i get compilation errors on `spinner1.getSelectedItem().toString();` in the part of the code where i'm reading the chosen item). – anderfo Jan 31 '12 at 07:11
  • your or new class has to implemented OnItemSelectedListener and then you just set this class as spinner.setOnItemSelectedListener(new MyOnItemSelectedListenerClass()); here's example http://stackoverflow.com/questions/2652414/how-do-you-get-the-selected-value-of-a-spinner-android – Sergey Benner Jan 31 '12 at 09:20
  • OK, i think i already have that, except that i'm using a button to get the values from the spinners. i've now added that part of my code to the example above. – anderfo Jan 31 '12 at 10:42
  • implement your View.OnClickListener for your button elsewhere in the class and remove the `final` from both of the spinners in order to set their adapter from different methods. make the spinners as fields of your Activity initialize them first in the onCreate() method and then use setAdapter() in the case 101 and 201 as the last point after setContentView() – Sergey Benner Jan 31 '12 at 10:56
  • thanks, now i found the reason why it forced me to choose `final`. the problem was that when i made the variables global (spinner1, adapter1, etc), i still defined them again inside `onCreate` (`Spinner spinner1 = ...`). Now after just writing `spinner1 = ...` I'm allowed to take away the final modifier and can use `setAdapter` in other methods. Anyway, my main problem is still there: The spinners are empty :( BTW I'll update the code above. – anderfo Feb 01 '12 at 01:30

1 Answers1

0

Remove this.setContentView(R.layout.main);

before

 try{
            spinner1.setAdapter(adapter1);
            spinner2.setAdapter(adapter2);
            spinner1.setSelection(1);
            spinner2.setSelection(2);
        } catch (Exception e){
            e.printStackTrace();
        }

in both of your cases.

working code below:

public class TestSpinner extends Activity {

private ArrayAdapter<CharSequence> adapter1;
private Spinner spinner1;
private ArrayAdapter<CharSequence> adapter2;
private Spinner spinner2;

@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.spinner);
    spinner1 = (Spinner) findViewById(R.id.spinner1);
    adapter1 = ArrayAdapter.createFromResource(
            this, R.array.planets_array, android.R.layout.simple_spinner_item);
    adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner1.setAdapter(adapter1);
    MyOnItemSelectedListener listener = new MyOnItemSelectedListener();

    spinner1.setOnItemSelectedListener(listener);
    spinner2 = (Spinner) findViewById(R.id.spinner2);
    adapter2 = ArrayAdapter.createFromResource(
            this, R.array.planets_array1, android.R.layout.simple_spinner_item);
    adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner2.setAdapter(adapter1);
    spinner2.setOnItemSelectedListener(listener);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    SubMenu faqMenu = menu.addSubMenu(0, 100, 1, "FAQ").setIcon(android.R.drawable.ic_menu_rotate);
    faqMenu.add(1, 101, 0, "set other planents");
    SubMenu langMenu = menu.addSubMenu(0, 200, 2, "LANGAUGE").setIcon(android.R.drawable.ic_menu_rotate);
    langMenu.add(1, 201, 0, "Language1");
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case 101:
            AlertDialog.Builder textbox = new AlertDialog.Builder(TestSpinner.this);
            textbox.setMessage("You've set new planets");
            textbox.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dlg, int i) {
                    dlg.dismiss();
                }
            });
            textbox.show();
            try {
                spinner1.setAdapter(adapter2);
                spinner2.setAdapter(adapter2);
                spinner1.setSelection(1);
                spinner2.setSelection(2);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return true;
        case 201:
            Locale locale = new Locale("en");
            Locale.setDefault(locale);
            Configuration config = new Configuration();
            config.locale = locale;
            getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
            Toast.makeText(this, "you've set old planets back!", Toast.LENGTH_LONG).show();
            try {
                spinner1.setAdapter(adapter1);
                spinner2.setAdapter(adapter1);
                spinner1.setSelection(1);
                spinner2.setSelection(2);
            } catch (Exception e) {
                e.printStackTrace();
            }

            return true;
    }
    return false;
}

public class MyOnItemSelectedListener implements AdapterView.OnItemSelectedListener {
    public void onItemSelected(AdapterView<?> parent,
                               View view, int pos, long id) {
        Toast.makeText(parent.getContext(), "The planet is " +
                parent.getItemAtPosition(pos).toString(), 1).show();
    }

    public void onNothingSelected(AdapterView parent) {
    }
}

private void refresh() {
        finish();
        Intent myIntent = new Intent(TestSpinner.this, TestSpinner.class);
        startActivity(myIntent);
    }
}

Cheers

Sergey Benner
  • 4,421
  • 2
  • 22
  • 29
  • the language setting doesn't work yet though - still need to restart app to reload strings if you select a different language than before. – anderfo Feb 01 '12 at 21:50
  • read this on how to change the languages http://developer.android.com/guide/topics/resources/localization.html and read this http://stackoverflow.com/questions/2264874/android-changing-locale-within-the-app-itself – Sergey Benner Feb 01 '12 at 22:21
  • In order to apply the language online you will still have to restart an activity where you apply it and you have to remember about the rotation too. I can provide the code to restart activity but you will have to remember the spinner's selections and other stuff before restarting it but it will restart at once and apply the language settings. Read the links I provided. – Sergey Benner Feb 01 '12 at 22:57
  • aha, yes I've used those two links before, but I haven't found the code for automatically restarting the app. would be great if you could give me a hint on that. in my case there's not much data that needs to be saved before restarting it. – anderfo Feb 02 '12 at 01:48
  • I have updated the answer with refresh() method. you should probably add an optionmenu for the language change and call this refresh() method right after you changed the locale it will restart the activity and apply your locale. – Sergey Benner Feb 02 '12 at 02:01