1

I have an android spinner that allows the user to select a translation. I can tap the spinner and it will reveal a list with available translations, but when I select an item in the list it will not appear in the spinner and neither does the onItemSelected method get called.

Here is the xml code for the spinner:

<Spinner
    android:id="@+id/trans_list"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_toRightOf="@+id/chap_list"
    android:layout_weight="1" />

Here is the relevant code for initiating the spinner. (edit) This code is ran from inside a Fragment class and not from my MainActivity class:

    trans_spinner = v.findViewById(R.id.trans_list);

    ArrayAdapter<String> adapter = new ArrayAdapter<>(v.getContext(), android.R.layout.simple_spinner_dropdown_item, translations);

    trans_spinner.setAdapter(adapter);

    trans_spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            String translation = trans_spinner.getItemAtPosition(trans_spinner.getSelectedItemPosition()).toString();
            Log.d("trans", translation);
            Toast.makeText(view.getContext(), translation, Toast.LENGTH_LONG).show();
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
            Log.d("test", "1");
        }
    });

    trans_spinner.setSelection(1);

Neither the onItemSelected() or onNothingSelected() method gets called when I select an item. I found this page describing an issue very similar to mine: Android Spinner will not launch OnItemSelected and current selected item is not displayed in Spinner However the user did not present a clear solution to their problem so it doesn't help me much.

I am not sure if it is relevant, but the items in the spinner are taken from an online webpage that provides JSON data to fill the spinner. This seems to work, as the options do appear in the spinner list. The issue is that upon selecting one of them, the spinner appears empty and the listener doesn't do anything.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115

4 Answers4

1

So I found out that the issue was actually because of how I obtained the list of strings to put inside the spinner. As mentioned in the original post, I am loading the string values from a webpage in JSON format. I'm using the Retrofit2 API for this.

The problem was caused by the fact that I was downloading this data and then initializing the spinner both in the onCreateView() method of my fragment. What I did to fix it is I created a new method that initializes the spinner, and then I would call it from the onResponse() method used by the Retrofit API. This means that it doesn't initialize the spinner until after it has finished downloading/populating the list of strings.

0

Java Code

public class MainActivity extends AppCompatActivity {

    Spinner spinner;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        spinner = findViewById(R.id.spinner);

        List<String> translations = new ArrayList<>();
        translations.add("string1");
        translations.add("string2");
        translations.add("string3");
        translations.add("string4");
        translations.add("string5");

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_spinner_dropdown_item, translations);
        spinner.setAdapter(adapter);

        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                Object getPosition = parent.getItemAtPosition(position);
                String value = getPosition.toString();
                Toast.makeText(getActivity(), value, Toast.LENGTH_LONG).show();
            }

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

            }
        });
    }
}

XML Code

<Spinner
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/spinner">
</Spinner>
letsCode
  • 2,774
  • 1
  • 13
  • 37
  • thanks for the suggestion, although it doesn't seem to work :/ I also replaced the trans_spinner parameter of getItemAtPosition() with parent but it didn't have any result either. – Martyn Corsair Aug 06 '18 at 13:13
  • What is translations? A list of strings? – letsCode Aug 06 '18 at 13:14
  • yeah it's a list of strings – Martyn Corsair Aug 06 '18 at 13:23
  • I updated my answer. This is a working example that has been tested. – letsCode Aug 06 '18 at 13:23
  • It still doesn't work in my project. The only differences at the moment are how I obtain the list of strings, and my code is ran from a fragment class instead of my main activity class. Do you think either of the two could be the cause? – Martyn Corsair Aug 06 '18 at 13:29
  • is the spinner being populated from your list? – letsCode Aug 06 '18 at 13:29
  • I updated the code... instead of getApplicationContext() its getActivity() – letsCode Aug 06 '18 at 13:31
  • yeah I use the list to populate the spinner. as far as I'm aware the list has the proper string values, because I can open the list of the spinner when testing the app and all the translations will appear. it just doesn't seem to display the selected translation after I choose one of the options in the spinner. I changed getApplicationContext() to getActivity(), although I think that currently it isn't executing the onItemSelected() method at all so any changes inside of it don't seem to have an effect. – Martyn Corsair Aug 06 '18 at 13:35
  • is it possible to show the entire fragment? how many lines of code is it? i think the error is the fragment itself... the application context is not being passed into it. – letsCode Aug 06 '18 at 13:40
  • It's 106 lines so I can post it; however I did some testing on my translations list and apparently the list is actually empty, since it has a size of 0. I guess this would be the cause of the issue, but then I don't know why I can still see the options inside the spinner when I test the app on my phone. I will see what happens when I make sure that the translations list is actually populated. – Martyn Corsair Aug 06 '18 at 13:42
  • https://pastebin.com/br8WqsUH here is the whole fragment class and https://pastebin.com/EGTNK8K4 here is the log output. From what I can see at first glance, the list is populated after the spinner is initialized, despite the popularization happening earlier in the code. I guess it has to do with the fact that it populates the list with data that has to be retrieved from a web page. I'll see if I can change the code appropriately. – Martyn Corsair Aug 06 '18 at 13:50
  • so you are pulling information using API. Where is this information? I have never used API before. I think the issue might be that the spinner is drawn before the data gets into it. Once the data gets into it, that is when you see the information in. Try adding a delay handler. to the spinner code https://stackoverflow.com/a/31041945/8200290 – letsCode Aug 06 '18 at 14:26
0

Add this code after init adapter

adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)

And to get the selected item inside onItemSelected

translations.get(position)
Tejashwi Kalp Taru
  • 2,994
  • 2
  • 20
  • 35
SANDIP CHAUDHARI
  • 166
  • 1
  • 2
  • 5
0
<Spinner
    android:id="@+id/planets_spinner"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" />

f the available choices for your spinner are pre-determined, you can provide them with a string array defined in a string resource file:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="planets_array">
        <item>Mercury</item>
        <item>Venus</item>
        <item>Earth</item>
        <item>Mars</item>
        <item>Jupiter</item>
        <item>Saturn</item>
        <item>Uranus</item>
        <item>Neptune</item>
    </string-array>
</resources>

With an array such as this one, you can use the following code in your Activity or Fragment to supply the spinner with the array using an instance of ArrayAdapter:

Spinner spinner = (Spinner) findViewById(R.id.spinner);
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
        R.array.planets_array, android.R.layout.simple_spinner_item);
// Specify the layout to use when the list of choices appears
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Apply the adapter to the spinner
spinner.setAdapter(adapter);

When the user selects an item from the drop-down, the Spinner object receives an on-item-selected event.

To define the selection event handler for a spinner, implement the AdapterView.OnItemSelectedListener interface and the corresponding onItemSelected() callback method. For example, here's an implementation of the interface in an Activity:

public class SpinnerActivity extends Activity implements OnItemSelectedListener { ...

public void onItemSelected(AdapterView<?> parent, View view,
        int pos, long id) {
    // An item was selected. You can retrieve the selected item using
    // parent.getItemAtPosition(pos)
}

public void onNothingSelected(AdapterView<?> parent) {
    // Another interface callback
}

}

The AdapterView.OnItemSelectedListener requires the onItemSelected() and onNothingSelected() callback methods.

Then you need to specify the interface implementation by calling setOnItemSelectedListener():

Spinner spinner = (Spinner) findViewById(R.id.spinner);
spinner.setOnItemSelectedListener(this);

If you implement the AdapterView.OnItemSelectedListener interface with your Activity or Fragment (such as in the example above), you can pass this as the interface instance.

Absar Alam
  • 102
  • 2
  • 9
  • thanks for the suggestion, I think it's pretty similar from how I did it originally (instead of making my fragment implement the OnItemSelectedListener interface, I just created a new Listener and assigned the onItemSelected and onNothingSelected methods). I figured it was worth a shot to make my fragment implement the interface, however it didn't fix the issue :/ – Martyn Corsair Aug 06 '18 at 13:23