wake-up-neo.com

Android Spinner mit Mehrfachauswahl

Wie erstelle ich ein Drehfeld, mit dem mehrere Elemente ausgewählt werden können, z. B. Drehfeld mit Kontrollkästchen?

56
Igor Filippov

Ich habe eine benutzerdefinierte Implementierung von MultiSpinner geschrieben. Es sieht aus wie ein normaler Spinner, hat aber Kontrollkästchen anstelle von Radiobuttons. Die ausgewählten Werte werden auf dem Drehfeld geteilt durch Komma angezeigt. Alle Werte sind standardmäßig aktiviert. Versuch es:

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);
    }
}

Sie verwenden es in XML wie folgt:

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

Und Sie übergeben Daten in Java wie folgt:

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

Außerdem müssen Sie den Listener implementieren, der das Array mit der gleichen Länge zurückgibt, wobei true oder false angezeigt wird, wenn ausgewählt oder nicht ausgewählt wird.

public void onItemsSelected(boolean[] selected);
138
David Vávra

Ich möchte nur eine alternative Version von @ Destils MultiSpinner zeigen (danke für Ihren inspirierenden Code), mit der Sie "Android: entries" in xml verwenden können, genau wie mit einem Spinner.

Zunächst wird kein Standardtext angezeigt, z. B. "Einen auswählen". Sie können ihn jedoch problemlos abrufen, indem Sie im Konstruktor ein zusätzliches ArrayAdapter festlegen.

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" />
9
vault

Soweit ich weiß, hat Spinner keinen Multiple-Choice-Modus. Stattdessen können Sie ein ImageButton erstellen und einen darstellbaren Abwärtspfeil auf der rechten Seite festlegen. Beim Klickereignis können Sie ein Dialog mit Elementen mit mehreren Kontrollkästchen öffnen.

Siehe hier: Android Multi Selection Dialogs

6
Vikas Patidar

Danke für den Beitrag! Großartige Lösung. Ich habe eine kleine Änderung an der Klasse (Methode setItems) vorgenommen, damit Benutzer bereits ausgewählte Elemente festlegen können, anstatt standardmäßig alle Elemente auf true zu setzen.

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
ᗩИᎠЯƎᗩ