08 July 2013

Android Spinner With Linked Values

In all the languages I've used I've had need for a drop-down. However they all seem to call it something different. .net calls it a combo box, html calls it a select tag and Android appears to call it a Spinner. Oh well! Normally I've used it as a key value pair. That is to say the string you select, isn't normally the same as the value you pass in the result. For example

<select>
    <option value="42">Volvo</option>
    <option value="24">Ford</option>
</select>

Android makes this a little tricky as it doesn't offer the same functionality, but using a hashmap provides a good way to go keep a map of options and their corresponding value.


private String[]            arrMuppetNames  = {"Kermit","Gonzo","Fuzzy","Animal"};
HashMap<String, Integer>    hashMuppets     = new HashMap<String, Integer>();

Setting up the hashmap is fairly trivial using the put method. In this example I used a set of if statements with hard coded values. Normally you'd get your values from a web service or a db call.

One problem I encountered with this method is when you setup your OnItemSelectedListener it will get fired immediately when  you start your application. Technically this is correct as something has been selected onLoad, but not normally desirable activity. So to combat this I've added in a --please select-- value and ignored this element. This is fairly common practice in HTML and works in Android too.

So this is the function that builds the spinner, note we're creating a new array with the zero value set to --please select--.

private void setSpinnerContent(String arrMuppets[]){
    Spinner spinner            = (Spinner) findViewById(R.id.muppets_spinner);
    String arrNewArray[]    = new String[arrMuppets.length + 1];
    
    //Add please select to spinner
    arrNewArray[0]    = this.getString(R.string.select_please);
    for(int i=0; i < arrMuppets.length; i++){
        arrNewArray[i+1]    = arrMuppets[i];
    }
    
    //Application of the Array to the Spinner
    ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(
            this,   
            android.R.layout.simple_spinner_item, 
            arrNewArray
    );
    spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
    spinner.setAdapter(spinnerArrayAdapter);
}

Then last of course is the selected item listener

private Spinner.OnItemSelectedListener spinnerListener = new Spinner.OnItemSelectedListener(){
    @Override
    public void onItemSelected(AdapterView<?> arg0, View arg1,int arg2, long arg3) {
        Spinner        my_spinner    = (Spinner) findViewById(R.id.muppets_spinner);
        
        //arg 3 is index, if 0 it means they clicked "--please select--"
        if(arg3 != 0){
            //get selected content
            String    strName        = my_spinner.getSelectedItem().toString();
            //use hasmap to translate that into a corresponding id. 
            int        intCatID    = hashMuppets.get(strName);
            
            Toast.makeText(getApplicationContext(), String.valueOf(intCatID), Toast.LENGTH_SHORT).show();
        }
    }
    @Override
    public void onNothingSelected(AdapterView<?> arg0) {
        //this is what happens if we select nothing.
        return;
    }
};

As you can see, we ignore the --please select-- and then call the hashmap to get the value.

Easy! Here's the full code:
http://pastebin.com/kVxwEHgm

1 comment:

phobeous said...

Nice post. Here yor're a link to a similar post I wrote about the same topic, but using Loaders. I think that both posts complement each other.

http://blog.linkedbytes.com/2013/06/30/linked-spinners-and-loaders-in-android/