Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ListPreference: use string-array as Entry and integer-array as Entry Values doesn't work

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?

like image 380
Santacrab Avatar asked Jul 05 '12 14:07

Santacrab


2 Answers

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.

like image 126
Egor Avatar answered Sep 18 '22 05:09

Egor


You can convert your entry values to strings to keep ListPreference happy and then convert them to ints when talking to the persistent data store.

  1. When setting the entry values, use strings instead of ints: "1", "2", "3" etc
  2. Make a custom IntListPreference that persists the values as ints
  3. 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);     }  } 
like image 21
Sam Avatar answered Sep 20 '22 05:09

Sam