J'utilise dans un fichier settings.xml un ListPreference. Je veux montrer à l'utilisateur une liste de 3 options à sélectionner. Lorsque l'utilisateur choisit l'une des options dans les paramètres, j'obtiens cette erreur:
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)
Voici le code de 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" />
Et voici les tableaux que j'utilise pour remplir les entrées:
<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>
Dans mon onSharedPreferenceChanged, j'utilise ces valeurs de cette manière:
@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;
}
}
Si j'utilise un autre tableau de chaînes pour entryValues cela fonctionne. Par exemple, si j'utilise le même tableau de chaînes que les valeurs et les entrées:
Android:entries="@array/date_alignement"
Android:entryValues="@array/date_alignement"
alors je dois changer un peu mon code mais ça marche:
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;
}
Pourquoi je ne peux pas utiliser un tableau de chaînes et un tableau d'entiers pour les entrées et les valeurs ListPreference?
La réponse est simple: parce que le Android est conçu de cette façon. Il utilise simplement des tableaux String
pour les entrées et les valeurs d'entrée et c'est tout. Et je ne vois aucun problème dans ce cas, puisque vous pouvez facilement convertir un String
en int
en utilisant la méthode Integer.parseInt()
. J'espère que cela vous aidera.
La réponse est répertoriée dans List Preference Documentation .
int findIndexOfValue (String value)
renverra l'index pour la valeur donnée et l'argument est pris comme une chaîne, donc le tableau entryValues doit être un tableau de chaînes pour obtenir ce travail.
Vous pouvez convertir vos valeurs d'entrée en chaînes pour garder ListPreference
heureux, puis les convertir en int
s lorsque vous parlez au magasin de données persistantes.
"1", "2", "3"
etcIntListPreference
personnalisé qui conserve les valeurs sous forme d'entierspreferences.xml
fichier, modifiez le <ListPreference>
dans une <your.app.package.IntListPreference>
Voici un exemple d'implémentation. Testé et fonctionnant sur 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);
}
}