Computer scienceMobileAndroidUser InterfaceUI components

Spinners

7 minutes read

When you create an account in some application, which information you need to provide? Often it includes your country and city. But the country name could be spelled differently and, as a developer, we don't want any ambiguity here. So it will be good to provide a list of all countries to choose from. But how can we do it? Making the input field show an error until a user guesses the name variant we want would be very annoying. Providing a huge list with hundreds of radio buttons doesn't look like a good UI/UX also. Lucky for us, Android Framework provides components that can help us with tasks like this.

In this topic, we will cover two widgets that can make user choice from some list of options more convenient: Spinner and AutoCompleteTextView.

Spinner

What is Spinner? Spinner provides a quick way to choose a value from a set with a dropdown list of options. Here is how it looks:

Spinner selection list

So, how can we create one? First of all, we should add Spinner to our layout.

<Spinner
    android:id="@+id/countries_spinner"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

Next, we need to populate it with choices. This can be performed with SpinnerAdapter interface. In this topic, we will use ArrayAdapter class and our choices will be available as an array but if you want to populate Spinner with choices from a database query, you can use CursorAdapter as well.

If in this case list of options is predefined, we can use XML resources to populate the adapter, so let's create our countries list in the strings.xml file.

<?xml version="1.0" encoding="utf-8"?>
<!--  strings.xml  -->

<resources>
    ...
    
    <string-array name="countries_array">
        <item>USA</item>
        <item>Germany</item>
        <item>Belgium</item>
        <item>France</item>
    </string-array>
</resources>

And then create and apply our ArrayAdapter with this list.

val spinner = findViewById<Spinner>(R.id.countries_spinner)

// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter.createFromResource(
    this,
    R.array.countries_array,
    // Specify the layout to use when the list of choices appears
    android.R.layout.simple_spinner_item
).also { adapter ->
    // Set the layout for the drop down list
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)

    // Apply the adapter to the spinner
    spinner.adapter = adapter
}

Or we can use a list of objects to define user choices.

// Create an ArrayAdapter using the string list and a default spinner layout
ArrayAdapter(
    this,
    android.R.layout.simple_spinner_item,
    listOf("USA", "Germany", "Belgium", "France")
).also { adapter ->
    // Set the layout for the drop down list
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)

    // Apply the adapter to the spinner
    spinner.adapter = adapter
}

As you can see, in both examples we provided android.R.layout.simple_spinner_item which is a predefined layout for selected item in the user control. Then we call setDropDownViewResource() to specify the layout for the items in the list with another predefined layout: android.R.layout.simple_spinner_item. You should use these layouts unless you want to design your own, but this is beyond the scope of this topic.

If you want to add a hint to the Spinner dropdown menu you can read about it on StackOverflow.

Get user selections

We created our Spinner and populated it with user choices. But now it is useless because we don't know what the user actually selected. How can we get this information?

To solve this we simply need to implement AdapterView.OnItemSelectedListener and apply it our Spinner just like this:

val listener = object : AdapterView.OnItemSelectedListener {
    override fun onItemSelected(parent: AdapterView<*>, view: View?, pos: Int, id: Long) {
        // We retrieve the selected item from the Spinner via its position in list
        val selectedItem = parent.getItemAtPosition(pos)

        // Show toast with selected item
        Toast.makeText(
            this@MainActivity,
            "Selected item: $selectedItem",
            Toast.LENGTH_SHORT
        ).show()
    }

    override fun onNothingSelected(parent: AdapterView<*>) {
        //This method will be invoked when the selection disappears from the view
        Toast.makeText(
            this@MainActivity,
            "Nothing selected",
            Toast.LENGTH_SHORT
        ).show()
    }
}


spinner.onItemSelectedListener = listener

And here is how it works:

You also can get user selections on demand with selectedItem and selectedItemPosition properties:

// Here we will get an item of Any type
val item: Any = spinner.selectedItem

// And we can retrieve typed item with its position from the adapter
val typedItem = adapter.getItem(spinner.selectedItemPosition)

AutoCompleteTextView

What is AutoCompleteTextView? Well, it is editable text view that will provide suggestions with drop down from the provided list. It looks like that:

So lets create one. First of all we need to add AutoCompleteTextView to our layout:

<AutoCompleteTextView
    android:hint="your country..."
    android:id="@+id/countries_autocomplete"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

Then we create and apply ArrayAdapter the same way we did it with Spinner, except that we use another default drop down item layout.

// Create an ArrayAdapter using the string list and a default drop down layout
ArrayAdapter(
    this,
    android.R.layout.simple_dropdown_item_1line,
    listOf("USA", "Germany", "Belgium", "France")
).also { adapter ->
    autoCompleteTextView.setAdapter(adapter)
}

We can also use setThreshold() method or android android:completionThreshold XML attribute to set the threshold value, the number of characters from which AutoCompleteTextView starts make its suggestion.

AdapterView.OnItemSelectedListener can also be assigned with setOnItemSelectedListener() method but it is not guaranteed that user will pick an item from suggestion list and not just leave his inputted text in the field.

Conclusion

In this topic we learned how to use Spinner and AutoCompleteTextView. Now you know how to:

  • Create Spinner and populate it with user choices using ArrayAdapter

  • Respond to user selections with AdapterView.OnItemSelectedListener

  • Create and populate with suggestions AutoCompleteTextView

10 learners liked this piece of theory. 1 didn't like it. What about you?
Report a typo