Android Spinner with multiple choices

How to create a spinner that allows you to select multiple elements, for example, a spinner with checkboxes?

+54
android android spinner
Feb 16 '11 at 11:11
source share
4 answers

I wrote a custom implementation of MultiSpinner. It looks like a regular spinner, but instead of fluctuations, it has flags. The selected values ​​are displayed on a counter separated by a comma. All values ​​are checked by default. Try:

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 someUnselected = false; for (int i = 0; i < items.size(); i++) { if (selected[i] == true) { spinnerBuffer.append(items.get(i)); spinnerBuffer.append(", "); } else { someUnselected = true; } } String spinnerText; if (someUnselected) { 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 as follows:

 <cz.destil.settleup.gui.MultiSpinner android:id="@+id/multi_spinner" /> 

And you pass it the data in Java as follows:

 MultiSpinner multiSpinner = (MultiSpinner) findViewById(R.id.multi_spinner); multiSpinner.setItems(items, getString(R.string.for_all), this); 

You also need to implement a listener that will return the same array of length, with true or false, to map the selected to unselected.

 public void onItemsSelected(boolean[] selected); 
+127
May 16 '11 at 19:43
source share

I just wanted to show an alternative version of @Destil MultiSpinner (thanks for your inspirational code) that allows you to use "android: entries" in xml, just like a spinner.

Initially, the default text is not displayed, for example, "select one", but you can easily get it by installing 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" /> 
+8
Apr 08 '14 at 15:08
source share

As far as I know, Spinner does not have a multiple choice mode. Instead, you can create an ImageButton and set the down arrow on the right side, and in the click event you can open Dialog elements with several checkboxes.

See here: Android Multi Selection Dialogs

+7
Feb 16 '11 at 12:10
source share

Thank you for message! Perfect solution. I made a small change to the class (setItems method) to allow users to set already selected elements, rather than selecting all elements 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); } 
+3
Jul 10 '13 at
source share



All Articles