Settings.xmlファイルでListPreferenceを使用しています。ユーザーに選択する3つのオプションのリストを表示したい。ユーザーが[設定]のオプションのいずれかを選択すると、次のエラーが表示されます。
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)
これは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" />
そして、ここに私がエントリを埋めるために使用する配列があります:
<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>
OnSharedPreferenceChangedで、これらの値を次のように使用します。
@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;
}
}
entryValuesに別の文字列配列を使用すると、機能します。たとえば、値とエントリとして同じ文字列配列を使用する場合:
Android:entries="@array/date_alignement"
Android:entryValues="@array/date_alignement"
その後、コードを少し変更する必要がありますが、動作します:
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;
}
ListPreferenceのエントリと値に文字列配列と整数配列を使用できないのはなぜですか?
答えは簡単です。なぜなら、Androidはこのように設計されているからです。エントリとエントリ値の両方にString
配列を使用するだけです。それですべてです。これは、Integer.parseInt()
メソッドを使用してString
をint
に簡単に変換できるためです。
答えは 環境設定ドキュメントのリスト にリストされています。
int findIndexOfValue (String value)
は指定された値のインデックスを返し、引数は文字列として取得されます。したがって、entryValues配列はこの作業を行うために文字列配列である必要があります。
エントリ値を文字列に変換してListPreference
を維持し、永続データストアと通信するときにそれらをint
sに変換できます。
"1", "2", "3"
などIntListPreference
を作成しますpreferences.xml
ファイル、<ListPreference>
に <your.app.package.IntListPreference>
以下に実装例を示します。 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);
}
}