ListPreference: use string-array as Entry and integer-array as Entry Values doesn't work
Solution 1
The answer is simple: because the Android is designed this way. It just uses String
arrays for both entries and entry values and that's all. And I can't see any problem in this fact, since you can easily convert a String
to an int
using the Integer.parseInt()
method. Hope this helps.
Solution 2
You can convert your entry values to strings to keep ListPreference
happy and then convert them to int
s when talking to the persistent data store.
- When setting the entry values, use strings instead of ints:
"1", "2", "3"
etc - Make a custom
IntListPreference
that persists the values as ints - In your
preferences.xml
file, change the<ListPreference>
into a<your.app.package.IntListPreference>
IntListPreference.java
Here's a sample implementation. Tested and working on AndroidX Preference 1.0.0.
public class IntListPreference extends ListPreference {
public IntListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public IntListPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public IntListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public IntListPreference(Context context) {
super(context);
}
@Override
protected boolean persistString(String value) {
int intValue = Integer.parseInt(value);
return persistInt(intValue);
}
@Override
protected String getPersistedString(String defaultReturnValue) {
int intValue;
if (defaultReturnValue != null) {
int intDefaultReturnValue = Integer.parseInt(defaultReturnValue);
intValue = getPersistedInt(intDefaultReturnValue);
} else {
// We haven't been given a default return value, but we need to specify one when retrieving the value
if (getPersistedInt(0) == getPersistedInt(1)) {
// The default value is being ignored, so we're good to go
intValue = getPersistedInt(0);
} else {
throw new IllegalArgumentException("Cannot get an int without a default return value");
}
}
return Integer.toString(intValue);
}
}
Solution 3
The answer is listed in List Preference Documentation.
int findIndexOfValue (String value)
will return the index for given value and the argument is taken as a String, so the entryValues array should be a string array to get this work.
Related videos on Youtube
Santacrab
Updated on July 05, 2022Comments
-
Santacrab almost 2 years
I'm using in a settings.xml file a ListPreference. I want to show the user a list of 3 options to select. When the user chooses one of the options in the Settings, I get this error:
java.lang.NullPointerException at android.preference.ListPreference.onDialogClosed(ListPreference.java:264) at android.preference.DialogPreference.onDismiss(DialogPreference.java:381) at android.app.Dialog$ListenersHandler.handleMessage(Dialog.java:1228) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4424) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) at dalvik.system.NativeStart.main(Native Method)
This is the code of the ListPreference:
<ListPreference android:entries="@array/date_alignement" android:entryValues="@array/date_alignement_values" android:key="settings_date_alignement" android:summary="@string/settings_date_alignement_summary" android:title="@string/settings_date_alignement_title" />
And here are the arrays I use to populate the entries:
<string-array name="date_alignement"> <item>"Top"</item> <item>"Center"</item> <item>"Bottom"</item> </string-array> <integer-array name="date_alignement_values"> <item >0</item> <item >1</item> <item >2</item> </integer-array>
In my onSharedPreferenceChanged I use those values in this way:
@Override public void onSharedPreferenceChanged( SharedPreferences sharedPreferences, String key) { //Text mAlignment = mPrefs.getInt(PREF_ALIGNMENT, 1); switch (mAlignment) { case 0: offsetY = mHeight/3.0f; break; case 2: offsetY = mHeight*2.0f/3.0f; break; default: offsetY = mHeight/2.0f; break; } }
If I use another string-array for the entryValues it works. For example if I use the same string array as values and entries:
android:entries="@array/date_alignement" android:entryValues="@array/date_alignement"
then I have to change my code a little but it works:
if(mAlignment.equalsIgnoreCase("center")) { offsetY = mHeight/2.0f; } else if(mAlignment.equalsIgnoreCase("top")) { offsetY = mHeight/3.0f; } else if(mAlignment.equalsIgnoreCase("bottom")) { offsetY = mHeight*2.0f/3.0f; }
Why I can't use a string-array and an integer-array for a ListPreference entries and values?
-
Yarik about 11 yearsI'm sory for stupid question, but what type of variable mAlignment do you use? and where did you get PREF_ALIGNMENT?
-
Santacrab over 10 yearsIn the first case mAlignment is an int. PREF_ALIGNMENT is the name of the entry in the SharedPreferences, where the alignment current value is stored
-
-
Santacrab almost 12 yearsOK, still don't get why it's not supported. Obviousely I can and I will convert it, but if is possible to use a specific structure (integer-array) instead of using the string one and convert it in int, it should work :) Thanks anyway!
-
Egor almost 12 years@Santacrab, If there were an integer array support, then there should also be float array support, double, char etc. It would be a big mess, so I think it's just easier to convert a String to whatever data type you need. Please accept the answer if you've found it useful.
-
Santacrab almost 12 yearsactually the integer-array structure exists. The problem is that it's not work when paired to the string one.
-
Tjaart over 11 years@Egor that is a silly reason. Of course you should be able to store different basic types. You can even serialise object types into your configs in .Net. And it isn't a big mess.
-
thom_nic about 11 yearsI've run into the same issue. It's easy make a
ListPreference
that gives back ints. See: kvance.livejournal.com/1039349.html -
theblang over 10 years@ThomNichols Nice! I was already rolling my own anyway. That was pretty simple nonetheless.
-
Muhammad Babar over 9 years
The answer is simple: because the Android is designed this way
are you telling me android is rigidly designed? I'm sorry but this can be a lame excuse but not an answer! -
njzk2 over 9 yearstypically, JSONObject.getInt tries to coerce values in int, sharedpreferences.getInt could do the same, and that would be sufficient
-
nizam.sp over 9 years@thom_nic: You made my day! The most elegant solution for this issue.
-
Gavriel almost 9 years@thom_nic: unfortunatelly I get a ClassCastException in this line: int intValue = getPersistedInt(0);
-
Vivek Maru over 6 yearsPlease describe the issue properly.
-
Nolan Amy over 5 years@thom_nic that livejournal link seems to be dead
-
HX_unbanned about 3 yearsThanks, @kasvith ! Could you add complete code sample, please?