Working with Spinners in Android

You have already studied about what Spinners are and how they work. So let's checkout an example and learn how we can implement it in our Android App.

In this tutorial, we are going to create an application that works with two Spinners, which are inder-dependent. The main layout of the application will contain our one TextView and two spinners as its child component views. So we need to customize the layout(shown in below image) where one Spinner is placed below the TextView and the other spinner is below the first spinner.

As the options inside the second Spinner will depend on what we select in the first Spinner, hence initially the second spinner will be hidden and it will only appear when user has selected one option from the first spinner.

The second spinner has the property isVisible equals to GONE, which means it exists in the layout but it will not be visible(or it will be hidden).

Hence, in the image below, it looks like it's not there. But you can try and change the value of isVisible to VISIBLE to see if it is there or not. But then change it back to GONE for now.


Spinner example in Android


The first Spinner(classSpinner) holds the list of classes(in school) to be selected by the user and based on that choice we will assign the values to the second Spinner(divSpinner). When user selects an optin from the second spinner too, then we will create a Toast and display the chosen values on screen.

So let's start, here we have the layout XML file. If you want, copy paste the below XML to start with this example in your local machine.

main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.akshay.studytonightandroid.MainActivity">

    <TextView
        android:id="@+id/tvDemo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:gravity="center"
        android:text="SPINNER DEMO"
        android:layout_alignParentLeft="true" />

    <Spinner
        android:id="@+id/classSpinner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tvDemo"
        android:layout_marginTop="25dp"
        android:entries="@array/items_class"/>

    <Spinner
        android:id="@+id/divSpinner"
        android:visibility="gone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/classSpinner"
        android:layout_toLeftOf="@id/classSpinner"
        android:layout_marginTop="10dp"
        />

</RelativeLayout>

NOTE: If you are getting an error in this, that is because you have not yet created the below data XML file. Once you will create that, the error in this file will be resolved.

As you can see, we have one TextView and two Spinner views inside the xml file along with a few properties specified.

To add items to the Spinner, there are two possible ways to provide it with a set of options. One by declaring an array and defining the items in it. But for this example, we will try the other way i.e. using an XML.

We can define a string array in XML like we have shown below in the strings.xml file. In Android, we must put the data XML files like our strings.xml file in app → res → values → strings.xml.

strings.xml

<resources>

    <string name="app_name">StudytonightAndroid</string>

    <string-array name="items_class">
        <item>Class 1</item>
        <item>Class 2</item>
        <item>Class 3</item>
        <item>Class 4</item>
    </string-array>

    <string-array name="items_div_class_1">
        <item>Div 1-A</item>
        <item>Div 1-B</item>
        <item>Div 1-C</item>
        <item>Div 1-D</item>
    </string-array>

    <string-array name="items_div_class_2">
        <item>Div 2-A</item>
        <item>Div 2-B</item>
        <item>Div 2-C</item>
        <item>Div 2-D</item>
    </string-array>

    <string-array name="items_div_class_3">
        <item>Div 3-A</item>
        <item>Div 3-B</item>
        <item>Div 3-C</item>
        <item>Div 3-D</item>
    </string-array>

    <string-array name="items_div_class_4">
        <item>Div 4-A</item>
        <item>Div 4-B</item>
        <item>Div 4-C</item>
        <item>Div 4-D</item>
    </string-array>

</resources>

By now, we are done with the following things:

  1. We have understood the design that we are creating in our Android App, which will have 1 TextView and 2 Spinners.
  2. We have defined the layout XML for the User interface.
  3. We have also defined our dataset for the Spinners.

In our dataset, string-array named items_class will be assigned to the classSpinner to display the class items in the dropdown list.

To add these entries to the spinner all we have to do is add a property android:entries="@array/items_class" in the main activity layout XML file. Doing so will assign the values present in the items_class array to the classSpinner.

As per the user's selection of the option from the first spinner, our second Spinner will appear along with options based on the first spinner's selection. We will do this through Java code as the user will select from the first dropdown at run time i.e. dynamically.

To handle the GUI events, we need to implement the code inside the MainActivity.java file. We will start by creating instances of both the spinners and then, assign the setOnItemSelectedListener() on both the spinners.

MainActivity.java

public class MainActivity extends AppCompatActivity 
{
    // these are the global variables
    Spinner classSpinner, divSpinner;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        classSpinner = (Spinner) findViewById(R.id.classSpinner);
        divSpinner = (Spinner) findViewById(R.id.divSpinner);
        
        // Class Spinner implementing onItemSelectedListener
        classSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() 
        {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) 
            {
                // do something upon option selection
            }
        
            @Override
            public void onNothingSelected(AdapterView<?> parent) 
            {
                // can leave this empty
            }
        });
        
        // Div Spinner implementing onItemSelectedListener
        divSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() 
        {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
            {
                // do something upon option selection
            }
        
            @Override
            public void onNothingSelected(AdapterView<?> parent)
            {
                // can leave this empty
            }
        
        });
    }
}

Changing Value of second Spinner based on first Spinner value

Inside the onItemSelected() method of classSpinner, you have to get the selected item from the dropdown list and based on that value, you have to assign entries i.e. options to divSpinner from the string-array resource. So add the following code inside classSpinner's onItemSelected() method.


classSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() 
{
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) 
    {
        // Get Selected Class name from the list
        String selectedClass = parent.getItemAtPosition(position).toString();
        switch (selectedClass) 
        {
            case "Class 1":
                // assigning div item list defined in XML to the div Spinner
                divSpinner.setAdapter(new ArrayAdapter<String>(MainActivity.this, 
                                android.R.layout.simple_spinner_dropdown_item, 
                                getResources().getStringArray(R.array.items_div_class_1)));
                break;
    
            case "Class 2":
                divSpinner.setAdapter(new ArrayAdapter<String>(MainActivity.this, 
                                android.R.layout.simple_spinner_dropdown_item, 
                                getResources().getStringArray(R.array.items_div_class_2)));
                break;
    
            case "Class 3":
                divSpinner.setAdapter(new ArrayAdapter<String>(MainActivity.this, 
                                android.R.layout.simple_spinner_dropdown_item, 
                                getResources().getStringArray(R.array.items_div_class_3)));
                break;
    
            case "Class 4":
                divSpinner.setAdapter(new ArrayAdapter<String>(MainActivity.this, 
                                android.R.layout.simple_spinner_dropdown_item, 
                                getResources().getStringArray(R.array.items_div_class_4)));
                break;
        }
        
        //set divSpinner Visibility to Visible
        divSpinner.setVisibility(View.VISIBLE);
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) 
    {
        // can leave this empty
    }
});

We can get the value of the selected class name from the ClassSpinner. For that we have used parent.getItemAtPosition(position).toString() method. Here, parent is the classSpinner view, and position is the position of the option selected.

Hence in parent.getItemAtPosition(position).toString() we are fetching the item(option) of the classSpinner dropdown present at the position which is stored in the parameter position.

Once we have the name of the class selected in the first dropdown, we can use a simple switch case to initialise the second dropdown with appropriate set of values.

We will initialise an ArrayAdapter with the respective string-array and will ste the adapter to our second spinner divSpinner.

To access the string-array from string resource in XML, we will have to use the method, getResources().getStringArray(ID_OF_ARRAY)

And at the end, we will set the visibility of the second spinner to be VISIBLE.


Creating a Toast to show the selcted values

Next, when the user selects an option from the second Spinner, we will create a Toast and display the selected values on screen.

// getting selected value from second spinner
selectedDiv = parent.getItemAtPosition(position).toString();
// creating Toast
Toast.makeText(MainActivity.this, "\n Class: \t " + selectedClass + "\n Div: \t" + selectedDiv, Toast.LENGTH_LONG).show();

Complete Code for MainActivity.java

Below is the complete code for MainActivity.java

package com.example.android.studytonight;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity 
{
    // these are the global variables
    Spinner classSpinner, divSpinner;
    // string variable to store selected values
    String selectedClass, selectedDiv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        classSpinner = (Spinner) findViewById(R.id.classSpinner);
        divSpinner = (Spinner) findViewById(R.id.divSpinner);
        
        // Class Spinner implementing onItemSelectedListener
        classSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() 
        {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) 
            {
                String selectedClass = parent.getItemAtPosition(position).toString();
                switch (selectedClass) 
                {
                    case "Class 1":
                        // assigning div item list defined in XML to the div Spinner
                        divSpinner.setAdapter(new ArrayAdapter<String>(MainActivity.this, 
                                        android.R.layout.simple_spinner_dropdown_item, 
                                        getResources().getStringArray(R.array.items_div_class_1)));
                        break;
            
                    case "Class 2":
                        divSpinner.setAdapter(new ArrayAdapter<String>(MainActivity.this, 
                                        android.R.layout.simple_spinner_dropdown_item, 
                                        getResources().getStringArray(R.array.items_div_class_2)));
                        break;
            
                    case "Class 3":
                        divSpinner.setAdapter(new ArrayAdapter<String>(MainActivity.this, 
                                        android.R.layout.simple_spinner_dropdown_item, 
                                        getResources().getStringArray(R.array.items_div_class_3)));
                        break;
            
                    case "Class 4":
                        divSpinner.setAdapter(new ArrayAdapter<String>(MainActivity.this, 
                                        android.R.layout.simple_spinner_dropdown_item, 
                                        getResources().getStringArray(R.array.items_div_class_4)));
                        break;
                }
                
                //set divSpinner Visibility to Visible
                divSpinner.setVisibility(View.VISIBLE);
            }
        
            @Override
            public void onNothingSelected(AdapterView<?> parent) 
            {
                // can leave this empty
            }
        });
        
        // Div Spinner implementing onItemSelectedListener
        divSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() 
        {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
            {
                selectedDiv = parent.getItemAtPosition(position).toString();
                /*
                    Now that we have both values, lets create a Toast to
                    show the values on screen
                */
                Toast.makeText(MainActivity.this, "\n Class: \t " + selectedClass +
                                    "\n Div: \t" + selectedDiv, Toast.LENGTH_LONG).show();
            }
        
            @Override
            public void onNothingSelected(AdapterView<?> parent)
            {
                // can leave this empty
            }
        
        });
    }
}

When you run your android application, you will get the first toast message by default because first item is already assigned to the spinner. Don't worry about it. Just go and try to change the spinner selection for class and division dropdowns and you should see the results as below images.

When you select Class option, as per the class selection your app will load other items in the DivSpinner and you can then select items from the second spinner. When you select an item from the second spinner, your app will display selected items on device screen.

Spinner Example in Android


Spinner Example in Android   Spinner Example in Android