How do I create spinner which allows to choose multiple items, i.e spinner with check boxes?
-
1AFAIK `Spinner` dosen't have a multiple choice mode. – Vikas Patidar Feb 16 '11 at 11:23
-
And how you suppose to show selected values in spinner – ingsaurabh Feb 16 '11 at 11:27
-
I mean how do I implement this: widget that works like spinner but shows a dialog with checkboxes and allows multiple choice. – Feb 16 '11 at 11:56
-
https://stackoverflow.com/a/47284385/1140304 – Milad Ahmadi Nov 14 '17 at 11:25
5 Answers
I have written custom implementation of MultiSpinner. It's looking similar to normal spinner, but it has checkboxes instead of radiobuttons. Selected values are displayed on the spinner divided by comma. All values are checked by default. Try it:
package cz.destil.settleup.gui;
public class MultiSpinner extends Spinner implements
OnMultiChoiceClickListener, OnCancelListener {
private List<String> items;
private boolean[] selected;
private String defaultText;
private MultiSpinnerListener listener;
public MultiSpinner(Context context) {
super(context);
}
public MultiSpinner(Context arg0, AttributeSet arg1) {
super(arg0, arg1);
}
public MultiSpinner(Context arg0, AttributeSet arg1, int arg2) {
super(arg0, arg1, arg2);
}
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
if (isChecked)
selected[which] = true;
else
selected[which] = false;
}
@Override
public void onCancel(DialogInterface dialog) {
// refresh text on spinner
StringBuffer spinnerBuffer = new StringBuffer();
boolean someSelected = false;
for (int i = 0; i < items.size(); i++) {
if (selected[i] == true) {
spinnerBuffer.append(items.get(i));
spinnerBuffer.append(", ");
someSelected = true;
}
}
String spinnerText;
if (someSelected) {
spinnerText = spinnerBuffer.toString();
if (spinnerText.length() > 2)
spinnerText = spinnerText.substring(0, spinnerText.length() - 2);
} else {
spinnerText = defaultText;
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getContext(),
android.R.layout.simple_spinner_item,
new String[] { spinnerText });
setAdapter(adapter);
listener.onItemsSelected(selected);
}
@Override
public boolean performClick() {
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setMultiChoiceItems(
items.toArray(new CharSequence[items.size()]), selected, this);
builder.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.setOnCancelListener(this);
builder.show();
return true;
}
public void setItems(List<String> items, String allText,
MultiSpinnerListener listener) {
this.items = items;
this.defaultText = allText;
this.listener = listener;
// all selected by default
selected = new boolean[items.size()];
for (int i = 0; i < selected.length; i++)
selected[i] = true;
// all text on the spinner
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getContext(),
android.R.layout.simple_spinner_item, new String[] { allText });
setAdapter(adapter);
}
public interface MultiSpinnerListener {
public void onItemsSelected(boolean[] selected);
}
}
You use it in XML like this:
<cz.destil.settleup.gui.MultiSpinner android:id="@+id/multi_spinner" />
And you pass data to it in Java like this:
MultiSpinner multiSpinner = (MultiSpinner) findViewById(R.id.multi_spinner);
multiSpinner.setItems(items, getString(R.string.for_all), this);
Also you need to implement the listener,which will return the same length array , with true or false to show selected to unselected..
public void onItemsSelected(boolean[] selected);

- 775
- 8
- 19

- 18,446
- 7
- 48
- 56
-
2how do you get the selected indexes from your component? I am able to use it but how can i get the selected items? Thank you – Thiago Sep 12 '11 at 18:58
-
1
-
2Works great! Awesome piece of code. Thanks for posting complete listing. – walkerk Oct 27 '11 at 19:41
-
Hi! Great piece of code! What is the license associated with your class ? Can it be used in commercial code ? – Rafael Nobre Aug 08 '12 at 12:41
-
@Destil forgot to add your name so you are notified of my last post. – Rafael Nobre Aug 08 '12 at 13:36
-
1@nobre: All code on SO is cc-wiki with attribution. See http://meta.stackexchange.com/questions/25956/what-is-up-with-the-source-code-license-on-stack-overflow – David Vávra Aug 09 '12 at 13:25
-
-
@Destil, I've written an alternative version of your code... I would like to hear a feedback from you :) – vault Apr 08 '14 at 15:10
-
@Destil I know this is really old, is there any chance you have a version where the Dialog is actually a dropdown so the look & feel of a spinner would still be the same? or would this be an issue since a dropdown wouldn't have a close button? – Mathijs Segers Jul 10 '14 at 14:14
-
@Destil, your code snippet is very nice! How can I implement on value change listener? – Rokas Aug 17 '14 at 19:20
-
1you have to add some description for getting value so newbie got easily by the way Wonderful work done. – Pratik Butani Oct 09 '14 at 12:16
-
4@Destil I want `DropDown` View instead of Dialog. is it Possible? – Pratik Butani Oct 10 '14 at 12:52
-
-
1@ツFellinLovewithAndroidツ It is possible but my answer is about a dialog. – David Vávra Dec 26 '14 at 14:35
-
stuck in same can anyone help http://stackoverflow.com/questions/29446088/how-to-get-spinner-values-in-textview/29487383?noredirect=1#comment47175570_29487383 – Apr 08 '15 at 13:42
-
I had a small bug with this code. When every choice was selected, it also showed the default text, so I fixed it here: https://gist.github.com/asiviero/54219136dd5cd7341a15 Thanks so much @Destil – asiviero Apr 13 '15 at 02:47
-
2
-
-
1For people in 2020, you will most likely get error at extends Spinner. You should replace the class to: public class MultiSpinner extends androidx.appcompat.widget.AppCompatSpinner implements – Izoman Feb 10 '20 at 14:44
-
Thanks. Is it possible to refresh the spinner view? Notifying the adapter doesn't work. It has to refresh because if someone picks "all" it has to uncheck the other boxes. – pete Aug 13 '20 at 04:37
I would just like to show an alternative version of @Destil's MultiSpinner (thank you for your inspiring code) which allows to use "android:entries" in xml, just like a spinner.
It doesn't initially show a default text, like "choose one", but you can easily obtain it by setting an additional ArrayAdapter
in the constructor.
MultiSpinner.java
package com.example.helloworld;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnMultiChoiceClickListener;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
/**
* Inspired by: http://stackoverflow.com/a/6022474/1521064
*/
public class MultiSpinner extends Spinner {
private CharSequence[] entries;
private boolean[] selected;
private MultiSpinnerListener listener;
public MultiSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MultiSpinner);
entries = a.getTextArray(R.styleable.MultiSpinner_android_entries);
if (entries != null) {
selected = new boolean[entries.length]; // false-filled by default
}
a.recycle();
}
private OnMultiChoiceClickListener mOnMultiChoiceClickListener = new OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
selected[which] = isChecked;
}
};
private DialogInterface.OnClickListener mOnClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// build new spinner text & delimiter management
StringBuffer spinnerBuffer = new StringBuffer();
for (int i = 0; i < entries.length; i++) {
if (selected[i]) {
spinnerBuffer.append(entries[i]);
spinnerBuffer.append(", ");
}
}
// Remove trailing comma
if (spinnerBuffer.length() > 2) {
spinnerBuffer.setLength(spinnerBuffer.length() - 2);
}
// display new text
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getContext(),
android.R.layout.simple_spinner_item,
new String[] { spinnerBuffer.toString() });
setAdapter(adapter);
if (listener != null) {
listener.onItemsSelected(selected);
}
// hide dialog
dialog.dismiss();
}
};
@Override
public boolean performClick() {
new AlertDialog.Builder(getContext())
.setMultiChoiceItems(entries, selected, mOnMultiChoiceClickListener)
.setPositiveButton(android.R.string.ok, mOnClickListener)
.show();
return true;
}
public void setMultiSpinnerListener(MultiSpinnerListener listener) {
this.listener = listener;
}
public interface MultiSpinnerListener {
public void onItemsSelected(boolean[] selected);
}
}
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MultiSpinner">
<attr name="android:entries" />
</declare-styleable>
</resources>
layout_main_activity.xml
<com.example.helloworld.MultiSpinner
android:id="@+id/multispinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/multispinner_entries" />

- 3,930
- 1
- 35
- 46
As far as I know Spinner
doesn't have a multiple choice mode. Instead you can create an ImageButton
and set a drawable down arrow in the right side and on the click event you can open a Dialog
having items with the multiple checkboxes.

- 50,140
- 28
- 121
- 140

- 42,865
- 22
- 93
- 106
Thanks for the post! Great solution. I made a small change to the class (method setItems) to allow users to set already selected items instead of selecting all items to true by default.
public void setItems(
List<String> items,
List<String> itemValues,
String selectedList,
String allText,
MultiSpinnerListener listener) {
this.items = items;
this.defaultText = allText;
this.listener = listener;
String spinnerText = allText;
// Set false by default
selected = new boolean[itemValues.size()];
for (int j = 0; j < itemValues.size(); j++)
selected[j] = false;
if (selectedList != null) {
spinnerText = "";
// Extract selected items
String[] selectedItems = selectedList.trim().split(",");
// Set selected items to true
for (int i = 0; i < selectedItems.length; i++)
for (int j = 0; j < itemValues.size(); j++)
if (selectedItems[i].trim().equals(itemValues.get(j))) {
selected[j] = true;
spinnerText += (spinnerText.equals("")?"":", ") + items.get(j);
break;
}
}
// Text for the spinner
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getContext(),
android.R.layout.simple_spinner_item, new String[] { spinnerText });
setAdapter(adapter);
}

- 2,122
- 5
- 29
- 41
-
-
1@eoinzy Suppose you have a list of Countries. In itemValues there are the ID's values (for example "us","uk","de","ch", or "1","2","3","4"), in items there are the descriptions ("USA,"United Kingdom","Germany","Switzerland"). – ᗩИᎠЯƎᗩ Aug 01 '13 at 21:13
-
I have the multi spinner working, but now how can I extract the selected itemValues into a comma sep string? '1,2,4,7' – Utrolig Jul 03 '15 at 19:03
-
You can check a simple library MultiSelectSpinner
You can simply do the following steps:
multiSelectSpinnerWithSearch.setItems(listArray1, new MultiSpinnerListener() {
@Override
public void onItemsSelected(List<KeyPairBoolData> items) {
for (int i = 0; i < items.size(); i++) {
if (items.get(i).isSelected()) {
Log.i(TAG, i + " : " + items.get(i).getName() + " : " + items.get(i).isSelected());
}
}
}
});
The listArray1
will be your array.
Check the full example here in How-To

- 60,504
- 58
- 273
- 437
-
-
1Why it is require to use KeyPairBoolData?.. Can't we use String array in your dependency? – Krishna Kachhela Aug 02 '21 at 08:52