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.