Comment créer un spinner qui permet de choisir plusieurs éléments, c'est-à-dire un spinner avec des cases à cocher?
J'ai écrit une implémentation personnalisée de MultiSpinner. Il ressemble à un spinner normal, mais il a des cases à cocher au lieu de boutons radio. Les valeurs sélectionnées sont affichées sur le spinner divisé par une virgule. Toutes les valeurs sont vérifiées par défaut. Essayez-le:
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);
}
}
Vous l'utilisez en XML comme ceci:
<cz.destil.settleup.gui.MultiSpinner Android:id="@+id/multi_spinner" />
Et vous lui passez des données en Java comme ceci:
MultiSpinner multiSpinner = (MultiSpinner) findViewById(R.id.multi_spinner);
multiSpinner.setItems(items, getString(R.string.for_all), this);
Vous devez également implémenter l'écouteur, qui renverra le même tableau de longueur, avec vrai ou faux pour afficher sélectionné à non sélectionné.
public void onItemsSelected(boolean[] selected);
Je voudrais juste montrer une version alternative du MultiSpinner de @ Destil (merci pour votre code inspirant) qui permet d'utiliser "Android: entrées" en xml, tout comme un spinner.
Il n'affiche pas initialement un texte par défaut, comme "choisissez-en un", mais vous pouvez facilement l'obtenir en définissant un ArrayAdapter
supplémentaire dans le constructeur.
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" />
Pour autant que je sache, Spinner
n'a pas de mode à choix multiples. Au lieu de cela, vous pouvez créer un ImageButton
et définir une flèche vers le bas sur le côté droit et sur l'événement de clic, vous pouvez ouvrir un Dialog
contenant des éléments avec plusieurs cases à cocher.
Reportez-vous ici: Boîtes de dialogue de sélection multiple Android
Merci pour le post! Excellente solution. J'ai apporté une petite modification à la classe (méthode setItems) pour permettre aux utilisateurs de définir les éléments déjà sélectionnés au lieu de sélectionner tous les éléments sur true par défaut.
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);
}