Android Spinner с множественным выбором
Как создать spinner, который позволяет выбрать несколько элементов, т. е. spinner с флажками?
4 ответа:
Я написал пользовательскую реализацию MultiSpinner. Он похож на обычный спиннер, но у него есть флажки вместо радиокнопок. Выбранные значения отображаются на счетчике, разделенном запятой. Все значения проверяются по умолчанию. Попробуйте:
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); } }
вы используете его в XML следующим образом:
<cz.destil.settleup.gui.MultiSpinner android:id="@+id/multi_spinner" />
и вы передаете ему данные на Java следующим образом:
MultiSpinner multiSpinner = (MultiSpinner) findViewById(R.id.multi_spinner); multiSpinner.setItems(items, getString(R.string.for_all), this);
Также вам нужно реализовать прослушиватель, который будет возвращать тот же массив длины, с true или false, чтобы показать выбранное для невыбранного..
public void onItemsSelected(boolean[] selected);
Я просто хотел бы показать альтернативную версию Мультиспиннера @Destil (спасибо за ваш вдохновляющий код), который позволяет использовать "android:записи" в xml, как и прядильщик.
он изначально не показывает текст по умолчанию, например "выбрать один", но вы можете легко получить его, установив дополнительный
ArrayAdapter
в конструктор.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" />
насколько я знаю
Spinner
не имеет режима множественного выбора. Вместо этого вы можете создатьImageButton
и установите рисуемую стрелку вниз в правой части, и на событии click вы можете открытьDialog
наличие элементов с несколькими флажками.смотрите здесь : Диалоги Выбора Android Multi
Спасибо за пост! Большое решение. Я внес небольшое изменение в класс (метод setItems), чтобы позволить пользователям устанавливать уже выбранные элементы вместо выбора всех элементов в true по умолчанию.
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); }