package com.devsourcenter.customspinner.model;
import android.content.Context;
/**
 * Interface to manage the color and the value of the Spinner
 */
public interface IEnumSpinner {
    /**
     * Get the localized value of the Spinner
     *
     * @param context Context
     * @return The value of the Spinner
     */
    public String getLabel(Context context);
    /**
     * Get the color of the selected value
     *
     * @return The integer representation of the color
     */
    public int getColor();
}
Now we have to implement the interface in our Enum:
package com.devsourcenter.customspinner.model.enums;
import android.content.Context;
import android.graphics.Color;
import com.devsourcenter.customspinner.AppResources;
import com.devsourcenter.customspinner.R;
import com.devsourcenter.customspinner.model.IEnumSpinner;
/**
 * This Enum is used to represent a color
 */
public enum ColorEnum implements IEnumSpinner {
    RED(R.string.label_red),
    BLUE(R.string.label_blue),
    GREEN(R.string.label_green);
    /**
     * localized label key
     */
    private int key;
    private ColorEnum (int key) {
        this.key = key;
    }
    // we override toString() in order to translate the labels in the drop-down
    // list
    @Override
    public String toString() {
        return AppResources.getContext().getString(key);
    }
    public String getLabel(Context context) {
        return context.getResources().getString(key);
    }
    public int getColor() {
        switch (this) {
            case RED:
                return Color.rgb(255, 0, 0);
            case BLUE:
                return Color.rgb(0, 0, 255);
            case GREEN:
                return Color.rgb(0, 255, 0);
        }
        
        return -1;
    }
}
We need to implement an Application class to get the context in the
toString() method of ColorEnum. In addition we also add the attribute android:name="AppResources" in the AndroidManifest.xml under the tag Application, in order to instantiate the class when the process for the application is created.package com.devsourcenter.customspinner;
import android.app.Application;
import android.content.Context;
/**
 * Class used to get a context in any part of the app
 */
public class AppResources extends Application {
    private static Context mContext;
    @Override
    public void onCreate() {
        super.onCreate();
        mContext = this;
    }
    public static Context getContext() {
        return mContext;
    }
}
At this point we can implement the Adapter associated to the the Spinner. The holder pattern is used to increase performance:
package com.devsourcenter.customspinner.model.adapter;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import com.devsourcenter.customspinner.R;
import com.devsourcenter.customspinner.model.IEnumSpinner;
/**
 * Adapter to fill Spinner with items
 */
public class EnumAdapter extends ArrayAdapter<IEnumSpinner> {
    Context mContext;
    int mLayoutResourceId;
    IEnumSpinner[] mItems;
    public EnumAdapter(Context context, int layoutResourceId,
            IEnumSpinner[] data) {
        super(context, layoutResourceId, data);
        this.mLayoutResourceId = layoutResourceId;
        this.mContext = context;
        this.mItems = data;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;
        Holder holder;
        if (row == null) {
            // at this point we inflate the view with our custom layout
            LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
            row = inflater.inflate(mLayoutResourceId, parent, false);
            holder = new Holder();
            holder.txtTitle = (TextView) row
                    .findViewById(R.id.textView_spinner);
            row.setTag(holder);
        } else {
            holder = (Holder) row.getTag();
        }
        IEnumSpinner item = mItems[position];
        holder.txtTitle.setText(item.getLabel(mContext));
        holder.txtTitle.setTextColor(item.getColor());
        return row;
    }
    static class Holder {
        TextView txtTitle;
    }
}
Finally we can create the Activity to include the Spinner:
package com.devsourcenter.customspinner;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Spinner;
import android.widget.Toast;
import com.devsourcenter.customspinner.model.adapter.EnumAdapter;
import com.devsourcenter.customspinner.model.enums.ColorEnum;
public class MainActivity extends Activity {
    private EnumAdapter mColorAdapter;
    private Spinner mSpinnerColor;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mColorAdapter = new EnumAdapter(this, R.layout.spinner_layout,
                ColorEnum.values());
        mSpinnerColor = (Spinner) findViewById(R.id.spinner_color);
        mSpinnerColor.setAdapter(mColorAdapter);
        mSpinnerColor
                .setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                    @Override
                    public void onItemSelected(AdapterView<?> parent,
                            View view, int position, long id) {
                        // get the enum selected
                        ColorEnum color = (ColorEnum) parent
                                .getItemAtPosition(position);
                        Toast.makeText(MainActivity.this,
                                color.getLabel(MainActivity.this),
                                Toast.LENGTH_LONG).show();
                        // do whatever you want
                    }
                    @Override
                    public void onNothingSelected(AdapterView<?> parent) {
                    }
                });
    }
}
We used this simple layout for the Activity (activity_main.xml):
<LinearLayout 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"
    android:orientation="horizontal"
    tools:context="com.devsourcenter.customspinner.MainActivity" >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="@string/label_choose"
        android:textAppearance="?android:attr/textAppearanceLarge" />
    <Spinner
        android:id="@+id/spinner_color"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>
And this is the layout for the Spinner (spinner_layout.xml):
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/textView_spinner"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:padding="7dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" >
    
</TextView>
We also provided translated enum labels for English:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">CustomSpinner</string>
    <string name="label_choose">Choose a color:</string>
    
    <string name="label_red">Red</string>
    <string name="label_blue">Blue</string>
    <string name="label_green">Green</string>
</resources>
Italian:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="label_red">Rosso</string>
    <string name="label_blue">Blu</string>
    <string name="label_green">Verde</string>
</resources>
and French:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="label_red">Rouge</string>
    <string name="label_blue">Bleu</string>
    <string name="label_green">Vert</string>
</resources>
Here is the result:
So you can simply define your Enum and your spinner_layout.xml to customize a Spinner.


