Spinner example in Android

android_spinner.png

Spinner provides a quick way to select one value from a set of options (like select dropdowns in HTML).

Some important properties of spinner are:

  • android:prompt. The prompt to display when the spinner’s dialog is shown.
  • android:spinnerMode. It defines display mode for spinner options. This property has two options: Dialog mode and DropDown mode. Dialog mode uses a dialog window for selecting spinner options and DropDown mode uses drop-down anchored to the Spinner for selecting spinner options.
  • android:entries. It references to an array resource that will populate the Spinner.

Create a spinner like any view and specify the android:entries attribute to specify the set of options:

<Spinner
    android:id="@+id/spinner"
    android:layout_width="wrap_content"
    android:entries="@array/planets_arrays"
    android:prompt="@string/planets_prompt"
    android:layout_height="wrap_content" />

Get the selected item out a spinner using:

Spinner spinner = (Spinner) findViewById(R.id.spinner);
String value = spinner.getSelectedItem().toString();

The data used to populate the Spinner can come from various sources but must be provided through a SpinnerAdapter like an ArrayAdapter if the source is an array or a CursorAdapter for result sets from database queries. ArrayAdapter and CursorAdapter (or SimpleCursorAdapter) are indirect sub classes of SpinnerAdapter.

String Array Resource

Specify the string array of options in res/values/planets_array.xml

<?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>
    </string-array>
</resources>

You can also load a spinner using an adapter for a dynamic source of options using an Adapter:

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);

The createFromResource method allows us to create an ArrayAdapter from the string array resource. The third layout argument passed to the constructor call is basically how the spinner control will look like when a manual selection is made (or the default one is showing up). The setDropDownViewResource method is used to specify the layout file used to represent each item in the dropdown. We use the in-built simple_spinner_dropdown_item layout file provided by the android platform.

ArrayList or Array of Objects Resource

We could pass on the data via an ArrayList or an array of objects (for example strings). Let’s see an example with ArrayList:

ArrayList<String> planets = new ArrayList<String>();
planets.add("Mercury");
planets.add("Venus");
planets.add("Earth");
planets.add("Mars");

ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, planets);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

spinner.setAdapter(adapter);

SQLite Resource

Displaying the contents of a Cursor in a Spinner is pretty straightforward.

First, we perform a query as discussed here, fetching just the Movie title and id (queryCols). Next, we create a SimpleCursorAdapter instance passing it the Cursor, an array of columns to display (adapterCols), and an array of views that the columns should be displayed in (adapterRowViews). Then, we set the Spinner’s Adapter to the `SimpleCursorAdapter.

String[] queryCols = new String[]{MovieDBHelper.ID, MovieDBHelper.TITLE};

SQLiteDatabase db = new MovieDBHelper(this).getReadableDatabase();
Cursor cursor = db.query(
        MovieDBHelper.TABLE_NAME, // the table to query
        queryCols,                // the columns to return
        null,                     // the columns for the WHERE clause
        null,                     // the values for the WHERE clause
        null,                     // don't group the rows
        null,                     // don't filter by row groups
        null                      // don't sort
);

String[] adapterCols = new String[]{MovieDBHelper.TITLE};
int[] adapterRowViews = new int[]{android.R.id.text1};

SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter(
        this, android.R.layout.simple_spinner_item, cursor, adapterCols, adapterRowViews, 0);
cursorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(cursorAdapter);

Custom Spinner dropdown example

For customization we need to create a custom adapter class and then extends our default adapter in that class.

Add spinner with custom background in your layout file

<Spinner
    android:background="@drawable/custom_spinner_background"
    android:spinnerMode="dropdown"
    android:id="@+id/spinner"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    />

Add following code to res/drawable/custom_spinner_background* as background for Spinner

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@android:color/white"/>
    <corners android:radius="4dp"></corners>
    <stroke android:color="#cccccc" android:width="1dp"/>
</shape>

Initialize custom Spinner and set custom adapter with planets list

Spinner spinner = (Spinner) findViewById(R.id.spinner);
String[] arPlanets = getResources().getStringArray(R.array.planets_array);
ArrayList planets = new ArrayList(Arrays.asList(arPlanets));
CustomSpinnerAdapter customSpinnerAdapter=new CustomSpinnerAdapter(ServiceActivity.this, planets);
spinner.setAdapter(customSpinnerAdapter);

Custom Spinner adapter code

public class CustomSpinnerAdapter extends BaseAdapter implements SpinnerAdapter {
    private final Context ctx;
    private ArrayList<String> items;

    public CustomSpinnerAdapter(Context ctx, ArrayList<String> items) {
        this.items = items;
        this.ctx = ctx;
    }

    public int getCount() {
        return items.size();
    }

    public Object getItem(int i) {
        return items.get(i);
    }

    public long getItemId(int i) {
        return (long)i;
    }

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        TextView txt = new TextView(ServiceActivity.this);
        txt.setPadding(16, 16, 16, 16);
        txt.setTextSize(18);
        txt.setGravity(Gravity.CENTER_VERTICAL);
        txt.setText(items.get(position));
        txt.setTextColor(Color.parseColor("#000000"));
        return  txt;
    }

    public View getView(int i, View view, ViewGroup viewgroup) {
        TextView txt = new TextView(ServiceActivity.this);
        txt.setGravity(Gravity.CENTER);
        txt.setPadding(16, 16, 16, 16);
        txt.setTextSize(16);
        txt.setCompoundDrawablesWithIntrinsicBounds(0, 0, android.R.drawable.arrow_down_float, 0);
        txt.setText(items.get(i));
        txt.setTextColor(Color.parseColor("#000000"));
        return  txt;
    }
}

Result

android_spinner_custom

Useful snippets

Setting spinner item based on value (rather than item position):

public void setSpinnerToValue(Spinner spinner, String value) {
    int index = 0;
    SpinnerAdapter adapter = spinner.getAdapter();
    for (int i = 0; i < adapter.getCount(); i++) {
        if (adapter.getItem(i).equals(value)) {
            index = i;
            break; 
        }
    }
    spinner.setSelection(index);
}

Getting the selected value of a Spinner is really easy. The getSelectedItem() method on the view object returns the value as an object that can be converted to a string using the toString() method. So basically we do something like this:

Spinner spPlanet = (Spinner) findViewById(R.id.planets);
String planet = spPlanet.getSelectedItem().toString().trim();

Receiving an event when the user selects an item is also very simple. Just need to implement the AdapterView.OnItemSelectedListener interface with the corresponding onItemSelected method:

spPlanet.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        String planet = parent.getItemAtPosition(position).toString();
        Toast.makeText(MainActivity.this, planet, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {}
});
comments powered by Disqus