Android
Spinner
Programmatically
Array
Tutorial

Android Create spinner programmatically from array

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Creating a Spinner programmatically is useful when the options depend on runtime data or when the entire view hierarchy is being built in code. The core steps are simple: create the Spinner, supply an adapter backed by your array, choose item layouts, and add the view to a parent container. The part that usually goes wrong is not the spinner itself, but forgetting that adapters, layout params, and selection callbacks all still matter when no XML is involved.

Create the Spinner and Data Source

A spinner needs a Context and a list of values. In Kotlin, a straightforward setup looks like this:

kotlin
val items = arrayOf("Red", "Green", "Blue")
val spinner = Spinner(this)

At this point, the spinner exists but has nothing to display. The next step is to connect it to an adapter.

Attach an ArrayAdapter

For simple text entries, ArrayAdapter is the normal choice.

kotlin
1val items = arrayOf("Red", "Green", "Blue")
2
3val adapter = ArrayAdapter(
4    this,
5    android.R.layout.simple_spinner_item,
6    items
7)
8adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
9
10val spinner = Spinner(this)
11spinner.adapter = adapter

Two layout resources are involved here:

  • 'simple_spinner_item for the collapsed view'
  • 'simple_spinner_dropdown_item for the drop-down rows'

If you skip setDropDownViewResource, the spinner may still work, but the drop-down appearance can be inconsistent.

Add the Spinner to a Parent Layout

Because the view is created in code, it must also be inserted into an existing container.

kotlin
1val root = findViewById<LinearLayout>(R.id.rootLayout)
2
3val spinner = Spinner(this)
4spinner.layoutParams = LinearLayout.LayoutParams(
5    LinearLayout.LayoutParams.MATCH_PARENT,
6    LinearLayout.LayoutParams.WRAP_CONTENT
7)
8
9root.addView(spinner)

A complete example combining the adapter and parent layout looks like this:

kotlin
1import android.os.Bundle
2import android.widget.ArrayAdapter
3import android.widget.LinearLayout
4import android.widget.Spinner
5import androidx.appcompat.app.AppCompatActivity
6
7class MainActivity : AppCompatActivity() {
8    override fun onCreate(savedInstanceState: Bundle?) {
9        super.onCreate(savedInstanceState)
10        setContentView(R.layout.activity_main)
11
12        val root = findViewById<LinearLayout>(R.id.rootLayout)
13        val items = arrayOf("Red", "Green", "Blue")
14
15        val spinner = Spinner(this)
16        val adapter = ArrayAdapter(
17            this,
18            android.R.layout.simple_spinner_item,
19            items
20        )
21        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
22
23        spinner.adapter = adapter
24        spinner.layoutParams = LinearLayout.LayoutParams(
25            LinearLayout.LayoutParams.MATCH_PARENT,
26            LinearLayout.LayoutParams.WRAP_CONTENT
27        )
28
29        root.addView(spinner)
30    }
31}

With this in place, the spinner behaves just like one declared in XML.

Handle Selection Events

A spinner is usually created because the app needs the selected value. Attach a listener as usual.

kotlin
1spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
2    override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
3        val selected = items[position]
4        println("Selected: $selected")
5    }
6
7    override fun onNothingSelected(parent: AdapterView<*>?) = Unit
8}

Remember that onItemSelected can fire during initialization, not only after a user tap. If that matters, guard the first callback explicitly.

Update the Spinner Later

If the list of items changes at runtime, update the adapter rather than replacing the whole spinner.

kotlin
1val mutableItems = mutableListOf("Red", "Green")
2val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, mutableItems)
3adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
4spinner.adapter = adapter
5
6mutableItems.add("Blue")
7adapter.notifyDataSetChanged()

That is usually cleaner than creating a new spinner every time the data changes.

When to Use a Custom Item Layout

The built-in layouts are fine for plain text. If you need icons, custom fonts, or more precise spacing, use your own row layout XML and pass it into the adapter. The rest of the programmatic spinner setup stays the same.

A good rule is:

  • use the built-in layout for simple text choices
  • use a custom row layout only when the UI actually needs it

Common Pitfalls

A common mistake is creating the spinner but never adding it to a parent layout. In that case, the code runs and no widget appears.

Another issue is forgetting to set the drop-down view resource. The spinner may render awkwardly or inconsistently depending on theme and Android version.

Developers also sometimes build the spinner correctly but then expect onItemSelected to fire only after user interaction. The spinner often reports an initial selection automatically.

Finally, if you are building views dynamically, keep all UI work on the main thread. Creating and attaching Android views from background threads will eventually fail.

Summary

  • Create the Spinner in code, then connect it to an ArrayAdapter built from your array.
  • Set both the item layout and the drop-down layout for predictable rendering.
  • Add the spinner to a real parent container and give it layout params.
  • Attach a selection listener if the app needs the chosen value.
  • Update the adapter, not the whole view, when the item list changes at runtime.

Course illustration
Course illustration

All Rights Reserved.