Android Adventures - Spinners
Written by Mike James   
Friday, 21 August 2015
Article Index
Android Adventures - Spinners
Item Selection
Dynamic change

Handling the selection

The next question is how do you discover that the user has made a selection?

The simple answer is that we have to hookup to the Spinner's events. As always there are three possible ways of doing this, and this should be revision -

  • create a sub-class of AdapterView.OnItemSelectedListener and then an instance
  • implement the AdapterView.OnItemSelectedListener interface as part of the activity
  • use an anonymous class

Of the three the anonymous class nearly always seems the easiest because Android Studio will generate the interface methods for you.

If you start typing the following line and use the autocomplete to help:

AdapterView.OnItemSelectedListener onSpinner=
     new AdapterView.OnItemSelectedListener(){

then Android Studio will generate:

AdapterView.OnItemSelectedListener onSpinner =
  new AdapterView.OnItemSelectedListener() {
 @Override
 public void onItemSelected(
  AdapterView<?> parent,
  View view,
  int position,
  long id) {
 }

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

 

It also adds an import for AdapterView. You still have to add a semicolon at end, however.

If  you don't use the auto-complete then you might have to type everything in - including the import. 

You can see at once that you have to implement two event handlers:

  • onItemSelected -  triggered when the user selects an item
  • onNothingSelected - triggered when the Spinner has no items or the user deselects all items

You might also wonder what the <?> are in the generated code?

Both events are generic and, as already explained, they can work with a range of different types.

The <?> is a type wildcard which essentially allows any type to be used. For example List<?> is a list of any type. Of course, the actual type isn't known until runtime and so every element of the List is treated as an Object type and it's up to you to cast it to something more specific.   

onItemSelected

Let's look at the onItemSelected event handler in more detail:

 public void onItemSelected(
  AdapterView<?> parent, 
  View view, 
  int position, 
  long id) {
 }

What is this AdapterView that has suddenly appeared?

As explained in a previous chapter all of the visible components of the UI correspond to View objects of one sort or another.

An AdapterView is the View object that corresponds to one of the displayed items in the Spinner that the ArrayAdapter is displayed in. You could, for example, use the AdapterView passed to the event handler to modify the look of the displayed item. 

The view parameter is just the child of the AdapterView that was actually clicked - an item can be composed of more than one View item. 

Finally the int position parameter and the long id provide the position of the view that was clicked in the adapter and the row id of the item that was selected.

You can populate a Spinner from a database - in this case the row id gives the database row number - which isn't necessarily the same as its position in the Spinner.

For a simple ArrayAdapter the position and id are the same. 

In most cases the only parameter you will be interested in is the int position which gives you the item the user selected. 

For example, place a TextView on the design surface and change the onItemSelected event handler to read:

@Override
public void onItemSelected(
 AdapterView<?> parent,
 View view,
 int position,
 long id) {
  TextView myTextView =
          (TextView) findViewById(R.id.textView);
  myTextView.setText(Integer.toString(position));
}

All that is happening is that the position parameter is displayed in the TextView. 

Finally to connect the eventhandling object to the Spinner we need to add it using its setOnItemSelectListener

spinner.setOnItemSelectedListener(onSpinner);

Putting all of this together gives the new onCreate:

@Override
protected void onCreate(
 Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);

 AdapterView.OnItemSelectedListener onSpinner =
      new AdapterView.OnItemSelectedListener() {

 @Override
 public void onItemSelected(
  AdapterView<?> parent,
  View view,
  int position,
  long id) {
   TextView myTextView =
     (TextView)findViewById(R.id.textView);
   myTextView.setText(Integer.toString(position));
 }

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

setContentView(R.layout.activity_main);
String[] country = {"Canada", "Mexico", "USA"};
ArrayAdapter<String> stringArrayAdapter=
                  new ArrayAdapter<String>(
 this,
 android.R.layout.simple_spinner_dropdown_item,country);
 Spinner spinner =
        (Spinner) findViewById(R.id.spinner);
 spinner.setAdapter(stringArrayAdapter);
 spinner.setOnItemSelectedListener(onSpinner);
}

If you now run the program you will see something like: 

spinner3

The position displayed corresponds to the element in the array that has been selected - counting from zero of course. 

Most of the time is it enough just to have the index number of the selected item but the AdapterView object has a few methods that enable you to get the selected item. 

If you want to review the selected item you could use the position to index the original ArrayAdapter or even the original String array - but these aren't generally available to the event handler. So to retrive the item you would use the getItemAtPosition method.

For example to display the country name you would modify the setText call to: 

 myTextView.setText(
 (String) parent.getItemAtPosition(position));

Notice that the selected item is returned as an object type and you have to cast it before you can do anything with it. 

There are a range of other methods that can be used to retrieve information or manipulate the selected element but for most simple applications the getItemAtPosition is all you really need to know.

 Androidgears



Last Updated ( Thursday, 13 October 2016 )