49
votes

I declare my Spinner in the following manner (it's very static so I have 2 string arrays in array.xml for titles and values)

<Spinner
    android:id="@+id/searchCriteria"
    android:entries="@array/searchBy"
    android:entryValues="@array/searchByValues" />

I expect spinner.getSelectedItem() to return an array [title, value] but in fact it returns just a title String. Is it ignoring android:entryValues? How do I get a value, not a title from it? Is this doable with XML only or do I need to create adapter and do it programmatically?

3
even if it doesn't work...i like the simplicity of that thoughtkritzikratzi

3 Answers

135
votes

Rather than the dual array method, why not fill your ArrayAdapter programmatically with objects of a known type and use that. I've written a tutorial of a similar nature (link at the bottom) that does this. The basic premise is to create an array of Java objects, tell the spinner about the, and then use those objects directly from the spinner class. In my example I have an object representing a "State" which is defined as follows:

package com.katr.spinnerdemo;

public class State {

// Okay, full acknowledgment that public members are not a good idea, however
// this is a Spinner demo not an exercise in java best practices.
public int id = 0;
public String name = "";
public String abbrev = "";

// A simple constructor for populating our member variables for this tutorial.
public State( int _id, String _name, String _abbrev )
{
    id = _id;
    name = _name;
    abbrev = _abbrev;
}

// The toString method is extremely important to making this class work with a Spinner
// (or ListView) object because this is the method called when it is trying to represent
// this object within the control.  If you do not have a toString() method, you WILL
// get an exception.
public String toString()
{
    return( name + " (" + abbrev + ")" );
}
}

Then you can populate a spinner with an array of these classes as follows:

       // Step 1: Locate our spinner control and save it to the class for convenience
    //         You could get it every time, I'm just being lazy...   :-)
    spinner = (Spinner)this.findViewById(R.id.Spinner01);

    // Step 2: Create and fill an ArrayAdapter with a bunch of "State" objects
    ArrayAdapter spinnerArrayAdapter = new ArrayAdapter(this,
          android.R.layout.simple_spinner_item, new State[] {   
                new State( 1, "Minnesota", "MN" ), 
                new State( 99, "Wisconsin", "WI" ), 
                new State( 53, "Utah", "UT" ), 
                new State( 153, "Texas", "TX" ) 
                });

    // Step 3: Tell the spinner about our adapter
    spinner.setAdapter(spinnerArrayAdapter);  

You can retrieve the selected item as follows:

State st = (State)spinner.getSelectedItem();

And now you have a bona fide Java class to work with. If you want to intercept when the spinner value changes, just implement the OnItemSelectedListener and add the appropriate methods to handle the events.

public void onItemSelected(AdapterView<?> parent, View view, int position, long id) 
{
    // Get the currently selected State object from the spinner
    State st = (State)spinner.getSelectedItem();

    // Now do something with it.
} 

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

You can find the whole tutorial here: http://www.katr.com/article_android_spinner01.php

55
votes

So if you came here because you want to have both label and value in the Spinner - here's how I did it:

  1. Just create your Spinner the usual way
  2. Define 2 equal size arrays in your array.xml file. One for labels, one for values
  3. Set your Spinner with android:entries="@array/labels"
  4. In your code - when you need a value do something like this (no you don't have to chain it)

    String selectedVal = getResources().getStringArray(R.array.values)[spinner
                             .getSelectedItemPosition()];
    

  5. And remember - these 2 arrays have to match each other as far as number slots and positions
8
votes

Abort, abort! I don't know what got into me but Spinner does not support android:entryValues attribute. That one is actually from ListPreference which does a similar thing (displays list of items in pop-up dialog). For what I need I will have to (alas) use the SpinnerAdapter