Spinner Android con scelta multipla
-
14-11-2019 - |
Domanda
Come posso creare Spinner che consente di scegliere più elementi, I.e Spinner con caselle di controllo?
Soluzione
Ho scritto implementazione personalizzata di Multispinner.Sembra simile allo spinner normale, ma ha caselle di controllo invece di radiobuttons.I valori selezionati vengono visualizzati sullo spinner diviso per comma.Tutti i valori sono controllati per impostazione predefinita.Provalo:
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);
}
}
.
Lo usi in XML come questo:
<cz.destil.settleup.gui.MultiSpinner android:id="@+id/multi_spinner" />
.
e tu passa i dati ad esso in Java come questo:
MultiSpinner multiSpinner = (MultiSpinner) findViewById(R.id.multi_spinner);
multiSpinner.setItems(items, getString(R.string.for_all), this);
.
È inoltre necessario implementare l'ascoltatore, che restituirà lo stesso array di lunghezza, con true o false per mostrare selezionato a ..
public void onItemsSelected(boolean[] selected);
. Altri suggerimenti
Vorrei solo mostrare una versione alternativa di @ Destil's Multispinner (grazie per il tuo codice ispiratore) che consente di utilizzare "Android: voci" in XML, proprio come uno spinner.
Non mostra inizialmente un testo predefinito, come "Scegli uno", ma è possibile ottenerlo facilmente impostando un ArrayAdapter
aggiuntivo nel costruttore.
.
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);
}
}
atts.xml
.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MultiSpinner">
<attr name="android:entries" />
</declare-styleable>
</resources>
layout_main_attività.xml
.<com.example.helloworld.MultiSpinner
android:id="@+id/multispinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/multispinner_entries" />
Per quanto ne so che Spinner
non ha una modalità a scelta multipla.Invece è possibile creare un ImageButton
e impostare una freccia a discesa nel lato destro e sul click event è possibile aprire un Dialog
avente elementi con le caselle di controllo multiple.
Fare riferimento qui: finestra di dialogo di selezione multi Android
.Grazie per il post!Grande soluzione.Ho fatto un piccolo cambiamento alla classe (metodo SetItems) per consentire agli utenti di impostare gli elementi già selezionati invece di selezionare tutti gli elementi su True per impostazione predefinita.
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);
}
.