How to Create an Android Spinner with Initial Text “Select One”

How to Create an Android Spinner with Initial Text "Select One"

6 June 2024 Stephan Petzl Leave a comment Tech-Help

Setting up a Spinner in Android that displays an initial prompt like “Select One” can be a bit tricky. This guide will walk you through the steps to achieve this using a custom adapter. The aim is to display the prompt text initially and replace it with the selected item once the user makes a choice, without showing the prompt in the dropdown list.

Solution Overview

We will create a custom adapter that wraps around the standard SpinnerAdapter. This custom adapter will handle displaying the initial prompt text and manage the selection of actual items. Here’s how you can do it:

Step-by-Step Implementation

1. Define the XML Layout for the Spinner

First, create the layout for the Spinner in your XML file:

<Spinner
    android:id="@+id/mySpinner"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:spinnerMode="dropdown" />

2. Create the Custom Adapter

Next, create a custom adapter class that decorates the existing SpinnerAdapter:

import android.content.Context;
import android.database.DataSetObserver;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.SpinnerAdapter;

/**
 * Decorator Adapter to allow a Spinner to show a 'Nothing Selected...' initially
 * displayed instead of the first choice in the Adapter.
 */
public class NothingSelectedSpinnerAdapter implements SpinnerAdapter, ListAdapter {

    protected static final int EXTRA = 1;
    protected SpinnerAdapter adapter;
    protected Context context;
    protected int nothingSelectedLayout;
    protected int nothingSelectedDropdownLayout;
    protected LayoutInflater layoutInflater;

    public NothingSelectedSpinnerAdapter(SpinnerAdapter spinnerAdapter, int nothingSelectedLayout, Context context) {
        this(spinnerAdapter, nothingSelectedLayout, -1, context);
    }

    public NothingSelectedSpinnerAdapter(SpinnerAdapter spinnerAdapter, int nothingSelectedLayout, int nothingSelectedDropdownLayout, Context context) {
        this.adapter = spinnerAdapter;
        this.context = context;
        this.nothingSelectedLayout = nothingSelectedLayout;
        this.nothingSelectedDropdownLayout = nothingSelectedDropdownLayout;
        layoutInflater = LayoutInflater.from(context);
    }

    @Override
    public final View getView(int position, View convertView, ViewGroup parent) {
        if (position == 0) {
            return getNothingSelectedView(parent);
        }
        return adapter.getView(position - EXTRA, null, parent);
    }

    protected View getNothingSelectedView(ViewGroup parent) {
        return layoutInflater.inflate(nothingSelectedLayout, parent, false);
    }

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        if (position == 0) {
            return nothingSelectedDropdownLayout == -1 ? new View(context) : getNothingSelectedDropdownView(parent);
        }
        return adapter.getDropDownView(position - EXTRA, null, parent);
    }

    protected View getNothingSelectedDropdownView(ViewGroup parent) {
        return layoutInflater.inflate(nothingSelectedDropdownLayout, parent, false);
    }

    @Override
    public int getCount() {
        int count = adapter.getCount();
        return count == 0 ? 0 : count + EXTRA;
    }

    @Override
    public Object getItem(int position) {
        return position == 0 ? null : adapter.getItem(position - EXTRA);
    }

    @Override
    public long getItemId(int position) {
        return position >= EXTRA ? adapter.getItemId(position - EXTRA) : position - EXTRA;
    }

    @Override
    public boolean hasStableIds() {
        return adapter.hasStableIds();
    }

    @Override
    public boolean isEmpty() {
        return adapter.isEmpty();
    }

    @Override
    public void registerDataSetObserver(DataSetObserver observer) {
        adapter.registerDataSetObserver(observer);
    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {
        adapter.unregisterDataSetObserver(observer);
    }

    @Override
    public boolean areAllItemsEnabled() {
        return false;
    }

    @Override
    public boolean isEnabled(int position) {
        return position != 0;
    }

}

3. Implement the Adapter in Your Activity

In your activity, you need to set up the Spinner with the custom adapter:

Spinner spinner = (Spinner) findViewById(R.id.mySpinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.planets_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(new NothingSelectedSpinnerAdapter(adapter, R.layout.contact_spinner_row_nothing_selected, this));

4. Define the Layout for the Prompt

Create a layout file named contact_spinner_row_nothing_selected.xml with the following content:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    style="?android:attr/spinnerItemStyle"
    android:singleLine="true"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ellipsize="marquee"
    android:textSize="18sp"
    android:textColor="#808080"
    android:text="[Select a Planet...]" />

Additional Resources

For more advanced configurations and troubleshooting, consider visiting our documentation pages:

Enhancing Your Testing Workflow with Repeato

Automating your testing process can significantly improve your development efficiency. With Repeato, a no-code test automation tool for iOS and Android, you can easily create, run, and maintain automated tests for your apps. Repeato uses computer vision and AI to streamline the process, allowing you to focus on developing great products rather than spending time on test creation and maintenance. Moreover, Repeato enables non-technical colleagues or QAs to handle test automation, making it an excellent tool for teams of all sizes.

Learn more about how Repeato can revolutionize your testing workflow by visiting our Android Testing Tool page.

Like this article? there’s more where that came from!