Skip to content

Commit 4a337ec

Browse files
Dianne HackbornAndroid (Google) Code Review
authored andcommitted
Merge "New preference for multi-selection check boxes." into jb-dev
2 parents 369d78f + 7746f91 commit 4a337ec

File tree

1 file changed

+313
-0
lines changed

1 file changed

+313
-0
lines changed
Lines changed: 313 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
/*
2+
* Copyright (C) 2012 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package android.preference;
18+
19+
import java.util.Arrays;
20+
21+
import android.app.AlertDialog.Builder;
22+
import android.content.Context;
23+
import android.content.DialogInterface;
24+
import android.content.res.TypedArray;
25+
import android.os.Parcel;
26+
import android.os.Parcelable;
27+
import android.util.AttributeSet;
28+
29+
/**
30+
* @hide
31+
* A {@link Preference} that displays a list of entries as
32+
* a dialog which allow the user to toggle each individually on and off.
33+
*
34+
* @attr ref android.R.styleable#ListPreference_entries
35+
* @attr ref android.R.styleable#ListPreference_entryValues
36+
*/
37+
public class MultiCheckPreference extends DialogPreference {
38+
private CharSequence[] mEntries;
39+
private String[] mEntryValues;
40+
private boolean[] mSetValues;
41+
private boolean[] mOrigValues;
42+
private String mSummary;
43+
44+
public MultiCheckPreference(Context context, AttributeSet attrs) {
45+
super(context, attrs);
46+
47+
TypedArray a = context.obtainStyledAttributes(attrs,
48+
com.android.internal.R.styleable.ListPreference, 0, 0);
49+
mEntries = a.getTextArray(com.android.internal.R.styleable.ListPreference_entries);
50+
if (mEntries != null) {
51+
setEntries(mEntries);
52+
}
53+
setEntryValuesCS(a.getTextArray(
54+
com.android.internal.R.styleable.ListPreference_entryValues));
55+
a.recycle();
56+
57+
/* Retrieve the Preference summary attribute since it's private
58+
* in the Preference class.
59+
*/
60+
a = context.obtainStyledAttributes(attrs,
61+
com.android.internal.R.styleable.Preference, 0, 0);
62+
mSummary = a.getString(com.android.internal.R.styleable.Preference_summary);
63+
a.recycle();
64+
}
65+
66+
public MultiCheckPreference(Context context) {
67+
this(context, null);
68+
}
69+
70+
/**
71+
* Sets the human-readable entries to be shown in the list. This will be
72+
* shown in subsequent dialogs.
73+
* <p>
74+
* Each entry must have a corresponding index in
75+
* {@link #setEntryValues(CharSequence[])}.
76+
*
77+
* @param entries The entries.
78+
* @see #setEntryValues(CharSequence[])
79+
*/
80+
public void setEntries(CharSequence[] entries) {
81+
mEntries = entries;
82+
mSetValues = new boolean[entries.length];
83+
mOrigValues = new boolean[entries.length];
84+
}
85+
86+
/**
87+
* @see #setEntries(CharSequence[])
88+
* @param entriesResId The entries array as a resource.
89+
*/
90+
public void setEntries(int entriesResId) {
91+
setEntries(getContext().getResources().getTextArray(entriesResId));
92+
}
93+
94+
/**
95+
* The list of entries to be shown in the list in subsequent dialogs.
96+
*
97+
* @return The list as an array.
98+
*/
99+
public CharSequence[] getEntries() {
100+
return mEntries;
101+
}
102+
103+
/**
104+
* The array to find the value to save for a preference when an entry from
105+
* entries is selected. If a user clicks on the second item in entries, the
106+
* second item in this array will be saved to the preference.
107+
*
108+
* @param entryValues The array to be used as values to save for the preference.
109+
*/
110+
public void setEntryValues(String[] entryValues) {
111+
mEntryValues = entryValues;
112+
Arrays.fill(mSetValues, false);
113+
Arrays.fill(mOrigValues, false);
114+
}
115+
116+
/**
117+
* @see #setEntryValues(CharSequence[])
118+
* @param entryValuesResId The entry values array as a resource.
119+
*/
120+
public void setEntryValues(int entryValuesResId) {
121+
setEntryValuesCS(getContext().getResources().getTextArray(entryValuesResId));
122+
}
123+
124+
private void setEntryValuesCS(CharSequence[] values) {
125+
setValues(null);
126+
if (values != null) {
127+
mEntryValues = new String[values.length];
128+
for (int i=0; i<values.length; i++) {
129+
mEntryValues[i] = values[i].toString();
130+
}
131+
}
132+
}
133+
134+
/**
135+
* Returns the array of values to be saved for the preference.
136+
*
137+
* @return The array of values.
138+
*/
139+
public CharSequence[] getEntryValues() {
140+
return mEntryValues;
141+
}
142+
143+
/**
144+
* Sets the current values.
145+
*/
146+
public void setValues(boolean[] values) {
147+
if (mSetValues != null) {
148+
Arrays.fill(mSetValues, false);
149+
Arrays.fill(mOrigValues, false);
150+
if (values != null) {
151+
System.arraycopy(values, 0, mSetValues, 0,
152+
values.length < mSetValues.length ? values.length : mSetValues.length);
153+
}
154+
}
155+
}
156+
157+
/**
158+
* Returns the summary of this ListPreference. If the summary
159+
* has a {@linkplain java.lang.String#format String formatting}
160+
* marker in it (i.e. "%s" or "%1$s"), then the current entry
161+
* value will be substituted in its place.
162+
*
163+
* @return the summary with appropriate string substitution
164+
*/
165+
@Override
166+
public CharSequence getSummary() {
167+
if (mSummary == null) {
168+
return super.getSummary();
169+
} else {
170+
return mSummary;
171+
}
172+
}
173+
174+
/**
175+
* Sets the summary for this Preference with a CharSequence.
176+
* If the summary has a
177+
* {@linkplain java.lang.String#format String formatting}
178+
* marker in it (i.e. "%s" or "%1$s"), then the current entry
179+
* value will be substituted in its place when it's retrieved.
180+
*
181+
* @param summary The summary for the preference.
182+
*/
183+
@Override
184+
public void setSummary(CharSequence summary) {
185+
super.setSummary(summary);
186+
if (summary == null && mSummary != null) {
187+
mSummary = null;
188+
} else if (summary != null && !summary.equals(mSummary)) {
189+
mSummary = summary.toString();
190+
}
191+
}
192+
193+
/**
194+
* Returns the currently selected values.
195+
*/
196+
public boolean[] getValues() {
197+
return mSetValues;
198+
}
199+
200+
/**
201+
* Returns the index of the given value (in the entry values array).
202+
*
203+
* @param value The value whose index should be returned.
204+
* @return The index of the value, or -1 if not found.
205+
*/
206+
public int findIndexOfValue(String value) {
207+
if (value != null && mEntryValues != null) {
208+
for (int i = mEntryValues.length - 1; i >= 0; i--) {
209+
if (mEntryValues[i].equals(value)) {
210+
return i;
211+
}
212+
}
213+
}
214+
return -1;
215+
}
216+
217+
@Override
218+
protected void onPrepareDialogBuilder(Builder builder) {
219+
super.onPrepareDialogBuilder(builder);
220+
221+
if (mEntries == null || mEntryValues == null) {
222+
throw new IllegalStateException(
223+
"ListPreference requires an entries array and an entryValues array.");
224+
}
225+
226+
mOrigValues = Arrays.copyOf(mSetValues, mSetValues.length);
227+
builder.setMultiChoiceItems(mEntries, mSetValues,
228+
new DialogInterface.OnMultiChoiceClickListener() {
229+
@Override
230+
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
231+
mSetValues[which] = isChecked;
232+
}
233+
});
234+
}
235+
236+
@Override
237+
protected void onDialogClosed(boolean positiveResult) {
238+
super.onDialogClosed(positiveResult);
239+
240+
if (positiveResult) {
241+
if (callChangeListener(getValues())) {
242+
return;
243+
}
244+
}
245+
System.arraycopy(mOrigValues, 0, mSetValues, 0, mSetValues.length);
246+
}
247+
248+
@Override
249+
protected Object onGetDefaultValue(TypedArray a, int index) {
250+
return a.getString(index);
251+
}
252+
253+
@Override
254+
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
255+
}
256+
257+
@Override
258+
protected Parcelable onSaveInstanceState() {
259+
final Parcelable superState = super.onSaveInstanceState();
260+
if (isPersistent()) {
261+
// No need to save instance state since it's persistent
262+
return superState;
263+
}
264+
265+
final SavedState myState = new SavedState(superState);
266+
myState.values = getValues();
267+
return myState;
268+
}
269+
270+
@Override
271+
protected void onRestoreInstanceState(Parcelable state) {
272+
if (state == null || !state.getClass().equals(SavedState.class)) {
273+
// Didn't save state for us in onSaveInstanceState
274+
super.onRestoreInstanceState(state);
275+
return;
276+
}
277+
278+
SavedState myState = (SavedState) state;
279+
super.onRestoreInstanceState(myState.getSuperState());
280+
setValues(myState.values);
281+
}
282+
283+
private static class SavedState extends BaseSavedState {
284+
boolean[] values;
285+
286+
public SavedState(Parcel source) {
287+
super(source);
288+
values = source.createBooleanArray();
289+
}
290+
291+
@Override
292+
public void writeToParcel(Parcel dest, int flags) {
293+
super.writeToParcel(dest, flags);
294+
dest.writeBooleanArray(values);
295+
}
296+
297+
public SavedState(Parcelable superState) {
298+
super(superState);
299+
}
300+
301+
public static final Parcelable.Creator<SavedState> CREATOR =
302+
new Parcelable.Creator<SavedState>() {
303+
public SavedState createFromParcel(Parcel in) {
304+
return new SavedState(in);
305+
}
306+
307+
public SavedState[] newArray(int size) {
308+
return new SavedState[size];
309+
}
310+
};
311+
}
312+
313+
}

0 commit comments

Comments
 (0)