Android Spinner has problems like.,

1.OnItemSelected listener will be fired when data is loadint at first time.

2.We can’t give label to the spinner(by default text).

Hbspinner.java overcomes this problems as per our basic need.

==>Hbspinner extends from button.It is added more methods seems to be Android spinner

==>Hbspinner provides Four types of spinners

=>Normal spinner: which is working just like Android spinner.

=>singleChoice spinner: spinner populates with single choice items.

=>multipleChoice spinner: spinner populates with multi choice items(with checkboxes).you can select more items

=>spinner using adapter:spinner is populating by using adapter.(in my example i am using android default layout: “android.R.layout.select_dialog_item”)

attr.xml:

[sourcecode language=”xml”]
<pre><?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="spinner">
<attr name="spinnervaluearray" format="reference" />
<attr name="prompt" format="string" />
<attr name="src" format="reference" />
<attr name="mode">
<enum name="single" value="0" />
<enum name="multiple" value="1" />
<enum name="single_radio" value="2" />
</attr>
</declare-styleable>

</resources>
[/sourcecode]

In layout/main.xml ,your declaration should be like this.

[sourcecode language=”xml”]

<pre><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:pref="http://schemas.android.com/apk/res/com.ramesh.spinner.demo"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:orientation="vertical" >
<com.ramesh.spinner.demo.HbSpinner
android:id="@+id/hbSpinner2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:drawableRight="@drawable/arrow_down_float"
android:text="Using Xml Attributes for Spinner "
pref:mode="single"
pref:prompt="Web Development"
pref:spinnervaluearray="@array/web"
pref:src="@drawable/ic_launcher" />
</LinearLayout>
[/sourcecode]

Hbspinner.java:

[sourcecode language=”java”]

package com.ramesh.spinner.demo;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.SparseBooleanArray;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;

public class HbSpinner extends Button {

private AlertDialog dialog;
private final static int INVALID = -1;
private CharSequence[] singeItems;
private OnSingleItemCallback listener;
private static OnMultiItemsSelectionCallback multilistener;
private String title = null;
private int icon = INVALID;
private Drawable iconDrawable;
private int mMode;
public static final int SINGLE = 0;
public static final int MULTIPLE = 1;
public static final int SINGLE_RADIO = 2;

public HbSpinner(Context context) {
super(context, null);
}

public HbSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
if (attrs != null) {
TypedArray a = getResources().obtainAttributes(attrs,
R.styleable.spinner);
int count = a.getIndexCount();

for (int i = 0; i < count; i++) {
int type = a.getIndex(i);
switch (type) {
case R.styleable.spinner_mode: {
setChoiceMode(a.getInt(type, 0));
}
break;
case R.styleable.spinner_spinnervaluearray: {
singeItems = a.getTextArray(type);
}
break;
case R.styleable.spinner_prompt: {
title = a.getString(type);
}
break;
case R.styleable.spinner_src: {
iconDrawable = a.getDrawable(type);
}
break;
default:
break;
}
}
a.recycle();
}

init();
}

public void init() {
setOnClickListener(onClick);
}

public void setDefaultText(String string) {
if (string != null)
this.setText(string);
}

public void setIcon(int icon) {
this.icon = icon;
}

public void setChoiceMode(int mode) {
if (mode < 3 && mode > INVALID)
mMode = mode;
// else
// new Exception(new Throwable("Illegal Mode selection"));
}

public void setPrompt(String title) {
this.title = title;
}

public void setSingleDataItems(String[] items) {
singeItems = items;
mMode = SINGLE;

}

/**
* Set on single items selection.
*
* @param callback
*/
public void setOnSingleItemSelectedListener(OnSingleItemCallback callback) {
listener = callback;
}

/**
* Set on Multiple items selection
*
* @param listener
*/
public void setOnMultiItemSelectedListener(
OnMultiItemsSelectionCallback listener) {
multilistener = listener;
}

@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (dialog != null && dialog.isShowing())
dialog.dismiss();
}

public OnClickListener onClick = new View.OnClickListener() {

@Override
public void onClick(View v) {

if (adapter != null) {
popupSpinnerAdapter();
} else if (SINGLE == mMode) {
popupSingleSpinner();
} else if (mMode == MULTIPLE) {
popupMultipleSpinner();
} else if (mMode == SINGLE_RADIO) {
popupSingleRadioSpinner();
}
}
};

public CharSequence[] getItems() {
return singeItems;
}

private void popupSingleSpinner() {
if (dialog != null && dialog.isShowing())
dialog.dismiss();
if (singeItems.length == 0) {
singeItems = new String[] { "" };
}

AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
if (title != null)
builder.setTitle(title);
if (icon != INVALID) {
builder.setIcon(icon);
} else if (iconDrawable != null) {
builder.setIcon(iconDrawable);
}
builder.setItems(singeItems, onDialogClick);
dialog = builder.create();
dialog.show();
}

private void popupMultipleSpinner() {
if (dialog != null && dialog.isShowing())
dialog.dismiss();
if (singeItems.length == 0) {
singeItems = new String[] { "" };
}

AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
if (title != null)
builder.setTitle(title);
if (icon != INVALID) {
builder.setIcon(icon);
} else if (iconDrawable != null) {
builder.setIcon(iconDrawable);
}
builder.setMultiChoiceItems(singeItems, null, onMultiClick);

builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int which) {
if (multilistener != null && checkedPositions.length > 0) {
multilistener.setMultiSelectedItemsCallback(HbSpinner.this,
checkedPositions);
checkedPositions = new int[0];
}
}
});
builder.setNegativeButton("Cancel", null);

dialog = builder.create();
dialog.show();
dialog.getListView().setOnItemClickListener(onItemSelected);

}

public DialogInterface.OnClickListener onDialogClick = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (mMode == SINGLE_RADIO)
checkedItem = which;

if (listener != null)
listener.onItemSelectedListener(HbSpinner.this,
singeItems[which], which);
HbSpinner.this.setText(singeItems[which]);
dialog.dismiss();
}
};
public DialogInterface.OnMultiChoiceClickListener onMultiClick = new DialogInterface.OnMultiChoiceClickListener() {

@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {

}
};

private int[] checkedPositions = new int[0];
public OnItemClickListener onItemSelected = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long arg3) {
ListView view = (ListView) arg0;
SparseBooleanArray sp = view.getCheckedItemPositions();
checkedPositions = new int[sp.size()];
for (int i = 0; i < sp.size(); i++)
checkedPositions[i] = sp.keyAt(i);
}
};

private int checkedItem = INVALID;

private void popupSingleRadioSpinner() {
if (dialog != null && dialog.isShowing())
dialog.dismiss();
if (singeItems.length == 0) {
singeItems = new String[] { "" };
}

AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
if (title != null)
builder.setTitle(title);
if (icon != INVALID) {
builder.setIcon(icon);
} else if (iconDrawable != null) {
builder.setIcon(iconDrawable);
}
builder.setSingleChoiceItems(singeItems, checkedItem, onDialogClick);
dialog = builder.create();
dialog.show();
}

public ListAdapter adapter;

public void setAdapter(ListAdapter adapter,
HbSpinnerAdapterCallback callbackAdapter) {
this.adapter = adapter;
this.callbackAdapter = callbackAdapter;
}

private void popupSpinnerAdapter() {
if (dialog != null && dialog.isShowing())
dialog.dismiss();
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
if (title != null)
builder.setTitle(title);
if (icon != INVALID) {
builder.setIcon(icon);
} else if (iconDrawable != null) {
builder.setIcon(iconDrawable);
}
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int which) {
if (callbackAdapter != null)
callbackAdapter.onItemselectionAdapter(HbSpinner.this,
which);
}
});// setSingleChoiceItems(singeItems,
// builder.setItems(singeItems, onDialogClick);
dialog = builder.create();
dialog.show();
}

public void setOnAdapterItemSelectionListener(
HbSpinnerAdapterCallback callback) {
callbackAdapter = callback;
}

public ListAdapter getAdapter() {
return adapter;
}

HbSpinnerAdapterCallback callbackAdapter;

interface HbSpinnerAdapterCallback {
/**
* Adapter items selection callback
*
* @param spinner
* {@link HbSpinner}
* @param position
* clicked position
*/
public void onItemselectionAdapter(HbSpinner spinner, int position);
}

interface OnMultiItemsSelectionCallback {

/**
* Multiple items selection callback
*
* @param spinner
* {@link HbSpinner}
* @param checked
* integer array which contains checked indexes
*/
public void setMultiSelectedItemsCallback(HbSpinner spinner,
int[] checked);
}

interface OnSingleItemCallback {
/**
* Single items selection callback
*
* @param spinner
* {@link HbSpinner}
* @param selectedItem
* selected item
* @param position
* selected position
*/
public void onItemSelectedListener(HbSpinner spinner,
CharSequence selectedItem, int position);
}
}

[/sourcecode]
you can find the source code here.
Screenshot:

screen shot
Custom spinner widget
Custom spinner widget in android ?
Tagged on:                     

0 thoughts on “Custom spinner widget in android ?

  • April 26, 2012 at 3:54 pm
    Permalink

    Very interesting, I must try out this code a spinner widget, thanks for posting.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *