diff options
author | Adam Powell <adamp@google.com> | 2010-04-08 16:24:46 -0700 |
---|---|---|
committer | Adam Powell <adamp@google.com> | 2010-04-15 10:18:17 -0700 |
commit | 212db7d3f8ce5297f4a556234a9c0675c697f1cf (patch) | |
tree | 1d6c441002808e657d6574d2708f4ce63daa83bc /core/java/android/preference | |
parent | 062fc7ce369758d5a26f83f12b50b11cd88e5def (diff) | |
download | frameworks_base-212db7d3f8ce5297f4a556234a9c0675c697f1cf.zip frameworks_base-212db7d3f8ce5297f4a556234a9c0675c697f1cf.tar.gz frameworks_base-212db7d3f8ce5297f4a556234a9c0675c697f1cf.tar.bz2 |
Added MultiSelectListPreference
Added set support to XmlUtils; added Set<String> functions to SharedPreferences.
MultiSelectListPreference allows multiple selection and persistence of
string preferences. Addresses bug 2575634.
Change-Id: Icd56022d444b0ce43cccf819cd7d600fdb00e88a
Diffstat (limited to 'core/java/android/preference')
-rw-r--r-- | core/java/android/preference/MultiSelectListPreference.java | 274 | ||||
-rw-r--r-- | core/java/android/preference/Preference.java | 63 |
2 files changed, 334 insertions, 3 deletions
diff --git a/core/java/android/preference/MultiSelectListPreference.java b/core/java/android/preference/MultiSelectListPreference.java new file mode 100644 index 0000000..42d555c --- /dev/null +++ b/core/java/android/preference/MultiSelectListPreference.java @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.preference; + +import android.app.AlertDialog.Builder; +import android.content.Context; +import android.content.DialogInterface; +import android.content.res.TypedArray; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.AttributeSet; + +import java.util.HashSet; +import java.util.Set; + +/** + * A {@link Preference} that displays a list of entries as + * a dialog. + * <p> + * This preference will store a set of strings into the SharedPreferences. + * This set will contain one or more values from the + * {@link #setEntryValues(CharSequence[])} array. + * + * @attr ref android.R.styleable#MultiSelectListPreference_entries + * @attr ref android.R.styleable#MultiSelectListPreference_entryValues + */ +public class MultiSelectListPreference extends DialogPreference { + private CharSequence[] mEntries; + private CharSequence[] mEntryValues; + private Set<String> mValues = new HashSet<String>(); + private Set<String> mNewValues = new HashSet<String>(); + private boolean mPreferenceChanged; + + public MultiSelectListPreference(Context context, AttributeSet attrs) { + super(context, attrs); + + TypedArray a = context.obtainStyledAttributes(attrs, + com.android.internal.R.styleable.MultiSelectListPreference, 0, 0); + mEntries = a.getTextArray(com.android.internal.R.styleable.MultiSelectListPreference_entries); + mEntryValues = a.getTextArray(com.android.internal.R.styleable.MultiSelectListPreference_entryValues); + a.recycle(); + } + + public MultiSelectListPreference(Context context) { + this(context, null); + } + + /** + * Sets the human-readable entries to be shown in the list. This will be + * shown in subsequent dialogs. + * <p> + * Each entry must have a corresponding index in + * {@link #setEntryValues(CharSequence[])}. + * + * @param entries The entries. + * @see #setEntryValues(CharSequence[]) + */ + public void setEntries(CharSequence[] entries) { + mEntries = entries; + } + + /** + * @see #setEntries(CharSequence[]) + * @param entriesResId The entries array as a resource. + */ + public void setEntries(int entriesResId) { + setEntries(getContext().getResources().getTextArray(entriesResId)); + } + + /** + * The list of entries to be shown in the list in subsequent dialogs. + * + * @return The list as an array. + */ + public CharSequence[] getEntries() { + return mEntries; + } + + /** + * The array to find the value to save for a preference when an entry from + * entries is selected. If a user clicks on the second item in entries, the + * second item in this array will be saved to the preference. + * + * @param entryValues The array to be used as values to save for the preference. + */ + public void setEntryValues(CharSequence[] entryValues) { + mEntryValues = entryValues; + } + + /** + * @see #setEntryValues(CharSequence[]) + * @param entryValuesResId The entry values array as a resource. + */ + public void setEntryValues(int entryValuesResId) { + setEntryValues(getContext().getResources().getTextArray(entryValuesResId)); + } + + /** + * Returns the array of values to be saved for the preference. + * + * @return The array of values. + */ + public CharSequence[] getEntryValues() { + return mEntryValues; + } + + /** + * Sets the value of the key. This should contain entries in + * {@link #getEntryValues()}. + * + * @param values The values to set for the key. + */ + public void setValues(Set<String> values) { + mValues = values; + + persistStringSet(values); + } + + /** + * Retrieves the current value of the key. + */ + public Set<String> getValues() { + return mValues; + } + + /** + * Returns the index of the given value (in the entry values array). + * + * @param value The value whose index should be returned. + * @return The index of the value, or -1 if not found. + */ + public int findIndexOfValue(String value) { + if (value != null && mEntryValues != null) { + for (int i = mEntryValues.length - 1; i >= 0; i--) { + if (mEntryValues[i].equals(value)) { + return i; + } + } + } + return -1; + } + + @Override + protected void onPrepareDialogBuilder(Builder builder) { + super.onPrepareDialogBuilder(builder); + + if (mEntries == null || mEntryValues == null) { + throw new IllegalStateException( + "MultiSelectListPreference requires an entries array and " + + "an entryValues array."); + } + + boolean[] checkedItems = getSelectedItems(); + builder.setMultiChoiceItems(mEntries, checkedItems, + new DialogInterface.OnMultiChoiceClickListener() { + public void onClick(DialogInterface dialog, int which, boolean isChecked) { + if (isChecked) { + mPreferenceChanged |= mNewValues.add(mEntries[which].toString()); + } else { + mPreferenceChanged |= mNewValues.remove(mEntries[which].toString()); + } + } + }); + mNewValues.clear(); + mNewValues.addAll(mValues); + } + + private boolean[] getSelectedItems() { + final CharSequence[] entries = mEntries; + final int entryCount = entries.length; + final Set<String> values = mValues; + boolean[] result = new boolean[entryCount]; + + for (int i = 0; i < entryCount; i++) { + result[i] = values.contains(entries[i].toString()); + } + + return result; + } + + @Override + protected void onDialogClosed(boolean positiveResult) { + super.onDialogClosed(positiveResult); + + if (positiveResult && mPreferenceChanged) { + final Set<String> values = mNewValues; + if (callChangeListener(values)) { + setValues(values); + } + } + mPreferenceChanged = false; + } + + @Override + protected Object onGetDefaultValue(TypedArray a, int index) { + final CharSequence[] defaultValues = a.getTextArray(index); + final int valueCount = defaultValues.length; + final Set<String> result = new HashSet<String>(); + + for (int i = 0; i < valueCount; i++) { + result.add(defaultValues[i].toString()); + } + + return result; + } + + @Override + protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { + setValues(restoreValue ? getPersistedStringSet(mValues) : (Set<String>) defaultValue); + } + + @Override + protected Parcelable onSaveInstanceState() { + final Parcelable superState = super.onSaveInstanceState(); + if (isPersistent()) { + // No need to save instance state + return superState; + } + + final SavedState myState = new SavedState(superState); + myState.values = getValues(); + return myState; + } + + private static class SavedState extends BaseSavedState { + Set<String> values; + + public SavedState(Parcel source) { + super(source); + values = new HashSet<String>(); + String[] strings = source.readStringArray(); + + final int stringCount = strings.length; + for (int i = 0; i < stringCount; i++) { + values.add(strings[i]); + } + } + + public SavedState(Parcelable superState) { + super(superState); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeStringArray(values.toArray(new String[0])); + } + + public static final Parcelable.Creator<SavedState> CREATOR = + new Parcelable.Creator<SavedState>() { + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } +} diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java index 197d976..381f794 100644 --- a/core/java/android/preference/Preference.java +++ b/core/java/android/preference/Preference.java @@ -16,8 +16,7 @@ package android.preference; -import java.util.ArrayList; -import java.util.List; +import com.android.internal.util.CharSequences; import android.content.Context; import android.content.Intent; @@ -28,7 +27,6 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.util.AttributeSet; -import com.android.internal.util.CharSequences; import android.view.AbsSavedState; import android.view.LayoutInflater; import android.view.View; @@ -36,6 +34,10 @@ import android.view.ViewGroup; import android.widget.ListView; import android.widget.TextView; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + /** * Represents the basic Preference UI building * block displayed by a {@link PreferenceActivity} in the form of a @@ -1250,6 +1252,61 @@ public class Preference implements Comparable<Preference>, OnDependencyChangeLis } /** + * Attempts to persist a set of Strings to the {@link android.content.SharedPreferences}. + * <p> + * This will check if this Preference is persistent, get an editor from + * the {@link PreferenceManager}, put in the strings, and check if we should commit (and + * commit if so). + * + * @param values The values to persist. + * @return True if the Preference is persistent. (This is not whether the + * value was persisted, since we may not necessarily commit if there + * will be a batch commit later.) + * @see #getPersistedString(Set) + * + * @hide Pending API approval + */ + protected boolean persistStringSet(Set<String> values) { + if (shouldPersist()) { + // Shouldn't store null + if (values.equals(getPersistedStringSet(null))) { + // It's already there, so the same as persisting + return true; + } + + SharedPreferences.Editor editor = mPreferenceManager.getEditor(); + editor.putStringSet(mKey, values); + tryCommit(editor); + return true; + } + return false; + } + + /** + * Attempts to get a persisted set of Strings from the + * {@link android.content.SharedPreferences}. + * <p> + * This will check if this Preference is persistent, get the SharedPreferences + * from the {@link PreferenceManager}, and get the value. + * + * @param defaultReturnValue The default value to return if either the + * Preference is not persistent or the Preference is not in the + * shared preferences. + * @return The value from the SharedPreferences or the default return + * value. + * @see #persistStringSet(Set) + * + * @hide Pending API approval + */ + protected Set<String> getPersistedStringSet(Set<String> defaultReturnValue) { + if (!shouldPersist()) { + return defaultReturnValue; + } + + return mPreferenceManager.getSharedPreferences().getStringSet(mKey, defaultReturnValue); + } + + /** * Attempts to persist an int to the {@link android.content.SharedPreferences}. * * @param value The value to persist. |