androidspinnerandroid-adapteronitemclicklisteneronitemselectedlistener

Changing Spinner list content after item is selected Android


Is there a way to change the displayed list inside of the Spinner after selection. I have 2 Strings, English and Finnish and I want to first change their language when one is selected, secondly change their order when the other is selected.

private void initLanguageSpinner() {

    List<String> spinnerLocale = new ArrayList<>();
    if ((currentdocumentLocale.toString().startsWith("deviceNameFi") || currentdocumentLocale.getLanguage().equals("fi"))) {
        spinnerLocale.add(getLocalizedResources(context, currentdocumentLocale).getString(R.string.finnish_language));
        spinnerLocale.add(getLocalizedResources(context, currentdocumentLocale).getString(R.string.english_language));
    } else {
        spinnerLocale.add(getLocalizedResources(context, currentdocumentLocale).getString(R.string.english_language));
        spinnerLocale.add(getLocalizedResources(context, currentdocumentLocale).getString(R.string.finnish_language));

    }

    ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(), R.layout.document_spinner_item, spinnerLocale);
    adapter.setDropDownViewResource(R.layout.document_spinner_dropdown_item);
    customerSelectedLanguageSpinner.setAdapter(adapter);
    customerSelectedLanguageSpinner.setSelection(0, false);
    customerSelectedLanguageSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            if (customerSelectedLanguageSpinner.getSelectedItem().toString().equals(getLocalizedResources(context, currentdocumentLocale).getString(R.string.finnish_language))) {
                onLocaleChangedFi();
                initLanguageSpinner();
            } else if (customerSelectedLanguageSpinner.getSelectedItem().toString().equals(getLocalizedResources(context, currentdocumentLocale).getString(R.string.english_language))) {
                onLocaleChangedEng();
                initLanguageSpinner();
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
    });
}

By doing this it basically does what I need, but it also goes into an endless loop since the onItemSelected is always called after initialization, even when I do the .setSelection(0, false). Is there a way to do what I need?

EDIT

So I tried creating a new adapter and then notifying it of changes.

private ArrayAdapter<String> spinnerAdapter;

private void initLanguageSpinner() {

    List<String> spinnerLocale = new ArrayList<>();
    if ((currentdocumentLocale.toString().startsWith("deviceNameFi") || currentdocumentLocale.getLanguage().equals("fi"))) {
        spinnerLocale.add(getLocalizedResources(context, currentdocumentLocale).getString(R.string.finnish_language));
        spinnerLocale.add(getLocalizedResources(context, currentdocumentLocale).getString(R.string.english_language));
    } else {
        spinnerLocale.add(getLocalizedResources(context, currentdocumentLocale).getString(R.string.english_language));
        spinnerLocale.add(getLocalizedResources(context, currentdocumentLocale).getString(R.string.finnish_language));

    }

    spinnerAdapter = new ArrayAdapter<>(getActivity(), R.layout.document_spinner_item, spinnerLocale);
    spinnerAdapter.setDropDownViewResource(R.layout.document_spinner_dropdown_item);
    customerSelectedLanguageSpinner.setAdapter(spinnerAdapter);
    customerSelectedLanguageSpinner.setSelection(0, false);
    customerSelectedLanguageSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            if (customerSelectedLanguageSpinner.getSelectedItem().toString().equals(getLocalizedResources(context, currentdocumentLocale).getString(R.string.finnish_language))) {
                setSpinnerAdapter(customerSelectedLanguageSpinner.getSelectedItem().toString()); 
                onLocaleChangedFi();
            } else if (customerSelectedLanguageSpinner.getSelectedItem().toString().equals(getLocalizedResources(context, currentdocumentLocale).getString(R.string.english_language))) {
                setSpinnerAdapter(customerSelectedLanguageSpinner.getSelectedItem().toString());
                onLocaleChangedEng();

            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
    });
}

private void setSpinnerAdapter(String language){
    if(language.equals("fi")){
        String[] myListFinnish = new String[] { getLocalizedResources(context, currentdocumentLocale).getString(R.string.finnish_language), getLocalizedResources(context, currentdocumentLocale).getString(R.string.english_language)};
        spinnerAdapter = new ArrayAdapter<>(getActivity(), R.layout.document_spinner_item, myListFinnish);
    } else {
        String[] myListEnglish = new String[] { getLocalizedResources(context, currentdocumentLocale).getString(R.string.english_language), getLocalizedResources(context, currentDocumentLocale).getString(R.string.finnish_language)};
        spinnerAdapter = new ArrayAdapter<>(getActivity(), R.layout.document_spinner_item, myListEnglish);
    }
    spinnerAdapter.setDropDownViewResource(R.layout.document_spinner_dropdown_item);
    spinnerAdapter.notifyDataSetChanged();
}

This way it does not even change the list strings or order. onLocaleChangedEng(); basically changes the Locale variable in the application.


Solution

  • your code is a dead loop. and if the adapter item data changed, such as add, remove, clear by adapter you can use notifyDataSetChanged method.

    Notifies the attached observers that the underlying data has been changed and any View reflecting the data set should refresh itself.

    adapter.clear()/add(object)/addAll();
    adapter.notifyDataSetChanged();
    
    

    then the view will update but not init.

    if the whole data changed, you can also recreate an adapter, and then set data

    dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, newStringList);
    dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinnerCategory.setAdapter(dataAdapter)
    

    At the same time, you can also clear and addAll, then notifyDataSetChanged

    adapter.clear() //remove all data;
    adapter.addAll(source);
    adapter.notifyDataSetChanged();
    
    //or remove it, then insert it in the first. that is acturl for your conditon
    adapter.remove(objcet) //remove special data;
    adapter.insert(object,index);
    adapter.notifyDataSetChanged();
    
    

    Secondly, you can also set a Tag to make when init the onItemSelected not called. the code like this:

    //define a tag when first it is 0
    int check = 0;
    //then in the onItemSelected add a check condition
    public void onItemSelected(AdapterView<?> parent, View arg1, int pos,long id) {
       if(++check> 1) {
          //do some things when item selected.
       }
    }
    
    

    use notifyDataSetChanged to update data, not every time init spinner. if you only want to remove the init selected effect, use the check tag.