简体   繁体   中英

Easy way to make the ListPreference multiple choice in Android?

I am trying to create a preference dialog window that allows the user to select more then one item in the list. Currently it only allows you to select one item. Is there an easy way to do this? I have looked all over the internet and not seen a way as of yet. Any help is appreciated!

Here is all the code you need!

http://blog.350nice.com/wp/wp-content/uploads/2009/07/listpreferencemultiselect.java

public class ListPreferenceMultiSelect extends ListPreference {
    //Need to make sure the SEPARATOR is unique and weird enough that it doesn't match one of the entries.
    //Not using any fancy symbols because this is interpreted as a regex for splitting strings.
    private static final String SEPARATOR = "OV=I=XseparatorX=I=VO";

    private boolean[] mClickedDialogEntryIndices;

    public ListPreferenceMultiSelect(Context context, AttributeSet attrs) {
        super(context, attrs);

        mClickedDialogEntryIndices = new boolean[getEntries().length];
    }

    @Override
    public void setEntries(CharSequence[] entries) {
        super.setEntries(entries);
        mClickedDialogEntryIndices = new boolean[entries.length];
    }

    public ListPreferenceMultiSelect(Context context) {
        this(context, null);
    }

    @Override
    protected void onPrepareDialogBuilder(Builder builder) {
        CharSequence[] entries = getEntries();
        CharSequence[] entryValues = getEntryValues();

        if (entries == null || entryValues == null || entries.length != entryValues.length ) {
            throw new IllegalStateException(
                    "ListPreference requires an entries array and an entryValues array which are both the same length");
        }

        restoreCheckedEntries();
        builder.setMultiChoiceItems(entries, mClickedDialogEntryIndices, 
                new DialogInterface.OnMultiChoiceClickListener() {
                    public void onClick(DialogInterface dialog, int which, boolean val) {
                        mClickedDialogEntryIndices[which] = val;
                    }
        });
    }

    public static String[] parseStoredValue(CharSequence val) {
        if ( "".equals(val) )
            return null;
        else
            return ((String)val).split(SEPARATOR);
    }

    private void restoreCheckedEntries() {
        CharSequence[] entryValues = getEntryValues();

        String[] vals = parseStoredValue(getValue());
        if ( vals != null ) {
            for ( int j=0; j<vals.length; j++ ) {
                String val = vals[j].trim();
                for ( int i=0; i<entryValues.length; i++ ) {
                    CharSequence entry = entryValues[i];
                    if ( entry.equals(val) ) {
                        mClickedDialogEntryIndices[i] = true;
                        break;
                    }
                }
            }
        }
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
//        super.onDialogClosed(positiveResult);

        CharSequence[] entryValues = getEntryValues();
        if (positiveResult && entryValues != null) {
            StringBuffer value = new StringBuffer();
            for ( int i=0; i<entryValues.length; i++ ) {
                if ( mClickedDialogEntryIndices[i] ) {
                    value.append(entryValues[i]).append(SEPARATOR);
                }
            }

            if (callChangeListener(value)) {
                String val = value.toString();
                if ( val.length() > 0 )
                    val = val.substring(0, val.length()-SEPARATOR.length());
                setValue(val);
            }
        }
    }
}

For which Android-Api-Level do you want this ?

When you use API-Level 11 you can use this MultiSelect Preference for Android 3.0 or higher

When you use API-Level smaller 11 you can use this Custom Implementation of MuliiSelect Preference

Thanks for the post, it helped me a lot. I made some changes to the class to allow users to update the summary shown in the preferences with the selected values.

In this way the user can see his choices without opening the Spinner.

Here are the added methods:

// Fills the Entry Values List
@Override
public void setEntryValues(CharSequence[] entryValues) {
    super.setEntryValues(entryValues);
    restoreCheckedEntries();
}

// Updates the Summary
@Override
public void setSummary(CharSequence entries) {
    String s = "";
    for (int x = 0; x < getEntryValues().length; x++)
        if (mClickedDialogEntryIndices[x])
            s += (s.equals("") ? "" : ", ") + getEntries()[x];
    super.setSummary(s);
}

The method setSummary must be called within the SettingsActivity.java here:

private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener 
= new Preference.OnPreferenceChangeListener() {

    @Override
    public boolean onPreferenceChange(Preference preference, Object value) {
        String stringValue = value.toString();

        if (preference instanceof ListPreferenceMultiSelect) {              
            ListPreferenceMultiSelect listPreference =
                (ListPreferenceMultiSelect) preference;
            listPreference.setSummary("");      
    }

    return true;
    }
};

The method setEntryValues can be called together with setEntries.

It worked for me! Compatible with Android 2.2 or newer.

Preferences are single values by definition. If you want to implement a multiple choice ListPreference you might have to subclass this class or android.preference.Preference and create your own implementation.

Alternatively you can call an activity from a simple preference screen and handle everything yourself.

You can store the values in a String preference with a separator or better yet, as various boolean preferences.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM