blob: 830de52576d8961d421881bff0021db85ff45bc8 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 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
17package android.preference;
18
Tor Norbye7b9c9122013-05-30 16:48:33 -070019import android.annotation.ArrayRes;
Mathew Inwoodf2217132018-08-17 13:41:55 +010020import android.annotation.UnsupportedAppUsage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import android.app.AlertDialog.Builder;
22import android.content.Context;
23import android.content.DialogInterface;
24import android.content.res.TypedArray;
25import android.os.Parcel;
26import android.os.Parcelable;
Alan Viverette94c02a12013-07-23 14:43:37 -070027import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.util.AttributeSet;
29
30/**
31 * A {@link Preference} that displays a list of entries as
32 * a dialog.
33 * <p>
34 * This preference will store a string into the SharedPreferences. This string will be the value
35 * from the {@link #setEntryValues(CharSequence[])} array.
Siarhei Vishniakouc6442332018-03-09 15:38:12 -080036 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037 * @attr ref android.R.styleable#ListPreference_entries
38 * @attr ref android.R.styleable#ListPreference_entryValues
Louis Pullen-Freilichb9596fa2018-11-19 17:40:56 +000039 *
40 * @deprecated Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
41 * <a href="{@docRoot}reference/androidx/preference/package-summary.html">
42 * Preference Library</a> for consistent behavior across all devices. For more information on
43 * using the AndroidX Preference Library see
44 * <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a>.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045 */
Louis Pullen-Freilichb9596fa2018-11-19 17:40:56 +000046@Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047public class ListPreference extends DialogPreference {
48 private CharSequence[] mEntries;
49 private CharSequence[] mEntryValues;
50 private String mValue;
Kenny Rootba636df2010-07-13 07:53:32 -070051 private String mSummary;
Mathew Inwoodf2217132018-08-17 13:41:55 +010052 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053 private int mClickedDialogEntryIndex;
Alan Viverette94c02a12013-07-23 14:43:37 -070054 private boolean mValueSet;
Alan Viverette617feb92013-09-09 18:09:13 -070055
56 public ListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
57 super(context, attrs, defStyleAttr, defStyleRes);
58
59 TypedArray a = context.obtainStyledAttributes(
60 attrs, com.android.internal.R.styleable.ListPreference, defStyleAttr, defStyleRes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061 mEntries = a.getTextArray(com.android.internal.R.styleable.ListPreference_entries);
62 mEntryValues = a.getTextArray(com.android.internal.R.styleable.ListPreference_entryValues);
63 a.recycle();
Kenny Rootba636df2010-07-13 07:53:32 -070064
65 /* Retrieve the Preference summary attribute since it's private
66 * in the Preference class.
67 */
68 a = context.obtainStyledAttributes(attrs,
Alan Viverette617feb92013-09-09 18:09:13 -070069 com.android.internal.R.styleable.Preference, defStyleAttr, defStyleRes);
Kenny Rootba636df2010-07-13 07:53:32 -070070 mSummary = a.getString(com.android.internal.R.styleable.Preference_summary);
71 a.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072 }
Kenny Rootba636df2010-07-13 07:53:32 -070073
Alan Viverette617feb92013-09-09 18:09:13 -070074 public ListPreference(Context context, AttributeSet attrs, int defStyleAttr) {
75 this(context, attrs, defStyleAttr, 0);
76 }
77
78 public ListPreference(Context context, AttributeSet attrs) {
Alan Viverette599d2a42013-09-16 13:48:29 -070079 this(context, attrs, com.android.internal.R.attr.dialogPreferenceStyle);
Alan Viverette617feb92013-09-09 18:09:13 -070080 }
81
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082 public ListPreference(Context context) {
83 this(context, null);
84 }
85
86 /**
87 * Sets the human-readable entries to be shown in the list. This will be
88 * shown in subsequent dialogs.
89 * <p>
90 * Each entry must have a corresponding index in
91 * {@link #setEntryValues(CharSequence[])}.
92 *
93 * @param entries The entries.
94 * @see #setEntryValues(CharSequence[])
95 */
96 public void setEntries(CharSequence[] entries) {
97 mEntries = entries;
98 }
99
100 /**
101 * @see #setEntries(CharSequence[])
102 * @param entriesResId The entries array as a resource.
103 */
Tor Norbye7b9c9122013-05-30 16:48:33 -0700104 public void setEntries(@ArrayRes int entriesResId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105 setEntries(getContext().getResources().getTextArray(entriesResId));
106 }
107
108 /**
109 * The list of entries to be shown in the list in subsequent dialogs.
110 *
111 * @return The list as an array.
112 */
113 public CharSequence[] getEntries() {
114 return mEntries;
115 }
116
117 /**
118 * The array to find the value to save for a preference when an entry from
119 * entries is selected. If a user clicks on the second item in entries, the
120 * second item in this array will be saved to the preference.
121 *
122 * @param entryValues The array to be used as values to save for the preference.
123 */
124 public void setEntryValues(CharSequence[] entryValues) {
125 mEntryValues = entryValues;
126 }
127
128 /**
129 * @see #setEntryValues(CharSequence[])
130 * @param entryValuesResId The entry values array as a resource.
131 */
Tor Norbye7b9c9122013-05-30 16:48:33 -0700132 public void setEntryValues(@ArrayRes int entryValuesResId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 setEntryValues(getContext().getResources().getTextArray(entryValuesResId));
134 }
135
136 /**
137 * Returns the array of values to be saved for the preference.
138 *
139 * @return The array of values.
140 */
141 public CharSequence[] getEntryValues() {
142 return mEntryValues;
143 }
144
145 /**
146 * Sets the value of the key. This should be one of the entries in
147 * {@link #getEntryValues()}.
148 *
149 * @param value The value to set for the key.
150 */
151 public void setValue(String value) {
Alan Viverette94c02a12013-07-23 14:43:37 -0700152 // Always persist/notify the first time.
153 final boolean changed = !TextUtils.equals(mValue, value);
154 if (changed || !mValueSet) {
155 mValue = value;
156 mValueSet = true;
157 persistString(value);
158 if (changed) {
159 notifyChanged();
160 }
161 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 }
163
164 /**
Kenny Rootba636df2010-07-13 07:53:32 -0700165 * Returns the summary of this ListPreference. If the summary
166 * has a {@linkplain java.lang.String#format String formatting}
167 * marker in it (i.e. "%s" or "%1$s"), then the current entry
168 * value will be substituted in its place.
169 *
170 * @return the summary with appropriate string substitution
171 */
172 @Override
173 public CharSequence getSummary() {
174 final CharSequence entry = getEntry();
Alan Viverette13e13dd2014-10-21 17:05:07 -0700175 if (mSummary == null) {
Kenny Rootba636df2010-07-13 07:53:32 -0700176 return super.getSummary();
177 } else {
Alan Viverette13e13dd2014-10-21 17:05:07 -0700178 return String.format(mSummary, entry == null ? "" : entry);
Kenny Rootba636df2010-07-13 07:53:32 -0700179 }
180 }
181
182 /**
183 * Sets the summary for this Preference with a CharSequence.
184 * If the summary has a
185 * {@linkplain java.lang.String#format String formatting}
186 * marker in it (i.e. "%s" or "%1$s"), then the current entry
187 * value will be substituted in its place when it's retrieved.
188 *
189 * @param summary The summary for the preference.
190 */
191 @Override
192 public void setSummary(CharSequence summary) {
193 super.setSummary(summary);
194 if (summary == null && mSummary != null) {
195 mSummary = null;
196 } else if (summary != null && !summary.equals(mSummary)) {
197 mSummary = summary.toString();
198 }
199 }
200
201 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 * Sets the value to the given index from the entry values.
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800203 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 * @param index The index of the value to set.
205 */
206 public void setValueIndex(int index) {
207 if (mEntryValues != null) {
208 setValue(mEntryValues[index].toString());
209 }
210 }
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 /**
213 * Returns the value of the key. This should be one of the entries in
214 * {@link #getEntryValues()}.
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800215 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 * @return The value of the key.
217 */
218 public String getValue() {
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800219 return mValue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 }
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800221
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 /**
223 * Returns the entry corresponding to the current value.
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800224 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 * @return The entry corresponding to the current value, or null.
226 */
227 public CharSequence getEntry() {
228 int index = getValueIndex();
229 return index >= 0 && mEntries != null ? mEntries[index] : null;
230 }
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 /**
233 * Returns the index of the given value (in the entry values array).
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800234 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 * @param value The value whose index should be returned.
236 * @return The index of the value, or -1 if not found.
237 */
238 public int findIndexOfValue(String value) {
239 if (value != null && mEntryValues != null) {
240 for (int i = mEntryValues.length - 1; i >= 0; i--) {
241 if (mEntryValues[i].equals(value)) {
242 return i;
243 }
244 }
245 }
246 return -1;
247 }
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 private int getValueIndex() {
250 return findIndexOfValue(mValue);
251 }
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 @Override
254 protected void onPrepareDialogBuilder(Builder builder) {
255 super.onPrepareDialogBuilder(builder);
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 if (mEntries == null || mEntryValues == null) {
258 throw new IllegalStateException(
259 "ListPreference requires an entries array and an entryValues array.");
260 }
261
262 mClickedDialogEntryIndex = getValueIndex();
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800263 builder.setSingleChoiceItems(mEntries, mClickedDialogEntryIndex,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 new DialogInterface.OnClickListener() {
265 public void onClick(DialogInterface dialog, int which) {
266 mClickedDialogEntryIndex = which;
267
268 /*
269 * Clicking on an item simulates the positive button
270 * click, and dismisses the dialog.
271 */
272 ListPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800273 postDismiss();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274 }
275 });
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 /*
278 * The typical interaction for list-based dialogs is to have
279 * click-on-an-item dismiss the dialog instead of the user having to
280 * press 'Ok'.
281 */
282 builder.setPositiveButton(null, null);
283 }
284
285 @Override
286 protected void onDialogClosed(boolean positiveResult) {
287 super.onDialogClosed(positiveResult);
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 if (positiveResult && mClickedDialogEntryIndex >= 0 && mEntryValues != null) {
290 String value = mEntryValues[mClickedDialogEntryIndex].toString();
291 if (callChangeListener(value)) {
292 setValue(value);
293 }
294 }
295 }
296
297 @Override
298 protected Object onGetDefaultValue(TypedArray a, int index) {
299 return a.getString(index);
300 }
301
302 @Override
303 protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
304 setValue(restoreValue ? getPersistedString(mValue) : (String) defaultValue);
305 }
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 @Override
308 protected Parcelable onSaveInstanceState() {
309 final Parcelable superState = super.onSaveInstanceState();
310 if (isPersistent()) {
311 // No need to save instance state since it's persistent
312 return superState;
313 }
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800314
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 final SavedState myState = new SavedState(superState);
316 myState.value = getValue();
317 return myState;
318 }
319
320 @Override
321 protected void onRestoreInstanceState(Parcelable state) {
322 if (state == null || !state.getClass().equals(SavedState.class)) {
323 // Didn't save state for us in onSaveInstanceState
324 super.onRestoreInstanceState(state);
325 return;
326 }
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 SavedState myState = (SavedState) state;
329 super.onRestoreInstanceState(myState.getSuperState());
330 setValue(myState.value);
331 }
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333 private static class SavedState extends BaseSavedState {
334 String value;
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 public SavedState(Parcel source) {
337 super(source);
338 value = source.readString();
339 }
340
341 @Override
342 public void writeToParcel(Parcel dest, int flags) {
343 super.writeToParcel(dest, flags);
344 dest.writeString(value);
345 }
346
347 public SavedState(Parcelable superState) {
348 super(superState);
349 }
350
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700351 public static final @android.annotation.NonNull Parcelable.Creator<SavedState> CREATOR =
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800352 new Parcelable.Creator<SavedState>() {
353 public SavedState createFromParcel(Parcel in) {
354 return new SavedState(in);
355 }
356
357 public SavedState[] newArray(int size) {
358 return new SavedState[size];
359 }
360 };
361 }
Siarhei Vishniakouc6442332018-03-09 15:38:12 -0800362
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363}