Android APIで提供されるMultiSelectListPreferenceの良い例を見つけるのに苦労しています。 this blog への参照をたくさん見ましたが、これは最終的には、実装する複数選択の設定ごとにクラスを作成したくありません。最終的には、単純な複数選択ダイアログの設定xmlを表示したいと思います(動的に値を入力します) )、およびaddPreferencesFromResource(R.xml.preferences);
の呼び出しに
現在、私は持っています:
<MultiSelectListPreference
Android:defaultValue=""
Android:enabled="true"
Android:entries="@array/pref_default_entries"
Android:entryValues="@array/pref_default_values"
Android:key="TargetList"
Android:persistent="true"
Android:summary="@string/TargetSummary"
Android:title="@string/TargetTitle" />
アクティビティのonCreate呼び出しでaddPreferencesFromResourceを呼び出そうとすると、次のエラーが発生します。
06-18 13:59:30.690: E/AndroidRuntime(6052): FATAL EXCEPTION: main
06-18 13:59:30.690: E/AndroidRuntime(6052): Java.lang.RuntimeException: Unable to start activity ComponentInfo{com.tracker/com.tracker.TrackerActivity}: Android.view.InflateException: Binary XML file line #37: Error inflating class Java.lang.reflect.Constructor
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:1818)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.app.ActivityThread.handleLaunchActivity(ActivityThread.Java:1834)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.app.ActivityThread.access$500(ActivityThread.Java:122)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1027)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.os.Handler.dispatchMessage(Handler.Java:99)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.os.Looper.loop(Looper.Java:132)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.app.ActivityThread.main(ActivityThread.Java:4126)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Java.lang.reflect.Method.invokeNative(Native Method)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Java.lang.reflect.Method.invoke(Method.Java:491)
06-18 13:59:30.690: E/AndroidRuntime(6052): at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:844)
06-18 13:59:30.690: E/AndroidRuntime(6052): at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:602)
06-18 13:59:30.690: E/AndroidRuntime(6052): at dalvik.system.NativeStart.main(Native Method)
06-18 13:59:30.690: E/AndroidRuntime(6052): Caused by: Android.view.InflateException: Binary XML file line #37: Error inflating class Java.lang.reflect.Constructor
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.preference.GenericInflater.createItem(GenericInflater.Java:397)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.preference.GenericInflater.onCreateItem(GenericInflater.Java:417)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.preference.GenericInflater.createItemFromTag(GenericInflater.Java:428)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.preference.GenericInflater.rInflate(GenericInflater.Java:481)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.preference.GenericInflater.inflate(GenericInflater.Java:326)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.preference.GenericInflater.inflate(GenericInflater.Java:263)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.preference.PreferenceManager.inflateFromResource(PreferenceManager.Java:269)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.preference.PreferenceActivity.addPreferencesFromResource(PreferenceActivity.Java:1366)
06-18 13:59:30.690: E/AndroidRuntime(6052): at com.tracker.TrackerActivity.onCreate(TrackerActivity.Java:30)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.app.Instrumentation.callActivityOnCreate(Instrumentation.Java:1050)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:1782)
06-18 13:59:30.690: E/AndroidRuntime(6052): ... 11 more
06-18 13:59:30.690: E/AndroidRuntime(6052): Caused by: Java.lang.reflect.InvocationTargetException
06-18 13:59:30.690: E/AndroidRuntime(6052): at Java.lang.reflect.Constructor.constructNative(Native Method)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Java.lang.reflect.Constructor.newInstance(Constructor.Java:416)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.preference.GenericInflater.createItem(GenericInflater.Java:383)
06-18 13:59:30.690: E/AndroidRuntime(6052): ... 21 more
06-18 13:59:30.690: E/AndroidRuntime(6052): Caused by: Java.lang.NullPointerException
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.content.res.AssetManager.getResourceTextArray(AssetManager.Java:215)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.content.res.Resources.getTextArray(Resources.Java:435)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.content.res.TypedArray.getTextArray(TypedArray.Java:628)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.preference.MultiSelectListPreference.onGetDefaultValue(MultiSelectListPreference.Java:210)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.preference.Preference.<init>(Preference.Java:257)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.preference.DialogPreference.<init>(DialogPreference.Java:69)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.preference.DialogPreference.<init>(DialogPreference.Java:90)
06-18 13:59:30.690: E/AndroidRuntime(6052): at Android.preference.MultiSelectListPreference.<init>(MultiSelectListPreference.Java:49)
06-18 13:59:30.690: E/AndroidRuntime(6052): ... 24 more
私はあなたの返事を楽しみにしています!
Sigristは正しいです。あなたが見ている最初のエラーを解決するためです。空の場合でも、デフォルト値を指定する必要があります。 [〜#〜] runtime [〜#〜]で値を提供したいのですが、完全な実装を台無しにしないので、これは私に役立ちました。
完全な実装を処理する必要はなく、実行時に値を提供する方法については、このコードを参照してください。
public class CalendarListPreference extends MultiSelectListPreference {
ContentResolver cr;
Cursor cursor;
String[] projection = new String[] {CalendarContract.Calendars.NAME, CalendarContract.Calendars.CALENDAR_DISPLAY_NAME};
String selection = "(" + CalendarContract.Calendars.VISIBLE + " = ?)";
String[] selectionArgs = new String[] { "1" };
public CalendarListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
List<CharSequence> entries = new ArrayList<CharSequence>();
List<CharSequence> entriesValues = new ArrayList<CharSequence>();
cr = context.getContentResolver();
cursor = cr.query(CalendarContract.Calendars.CONTENT_URI, projection, selection, selectionArgs, null);
while (cursor.moveToNext()) {
String name = cursor.getString(0);
String displayName = cursor.getString(1);
entries.add(name);
entriesValues.add(displayName);
}
setEntries(entries.toArray(new CharSequence[]{}));
setEntryValues(entriesValues.toArray(new CharSequence[]{}));
}
}
私のstrings.xmlで
<string-array name="pref_calendar_list_default">
</string-array>
私の好み.xmlで
<com.mynameistodd.autovolume.CalendarListPreference
Android:defaultValue="@array/pref_calendar_list_default"
Android:key="@string/pref_calendar_list_key"
Android:summary="@string/pref_calendar_list_summary"
Android:title="@string/pref_calendar_list_title"
Android:dependency="@string/pref_calendar_enabled_key"/>
これは少し古い質問であることはわかっていますが、役に立ったので、これが私の答えです!
DefaultValuesプロパティを指定する必要があります
<MultiSelectListPreference
Android:dialogTitle="@string/mode_repeat"
Android:key="mode_repeat"
Android:summary=""
Android:title="@string/mode_repeat"
Android:entries="@array/weekdays"
Android:entryValues="@array/weekdays_values"
Android:defaultValue="@array/empty_array"
/>
デフォルト値が必要ない場合は、空の配列をstrings.xmlに作成します
<string-array name="empty_array"/>
レベル11より前のAPIでAndroid=を実行しているデバイス用にMultiSelectListPreferenceを作成しました。
https://Gist.github.com/cardil/4754571
package pl.wavesoftware.widget;
import Java.util.ArrayList;
import Java.util.Arrays;
import Java.util.Iterator;
import Java.util.List;
import Android.app.AlertDialog.Builder;
import Android.content.Context;
import Android.content.DialogInterface;
import Android.content.DialogInterface.OnMultiChoiceClickListener;
import Android.content.res.TypedArray;
import Android.preference.ListPreference;
import Android.util.AttributeSet;
public class MultiSelectListPreference extends ListPreference {
private String separator;
private static final String DEFAULT_SEPARATOR = "\u0001\u0007\u001D\u0007\u0001";
private boolean[] entryChecked;
public MultiSelectListPreference(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
entryChecked = new boolean[getEntries().length];
separator = DEFAULT_SEPARATOR;
}
public MultiSelectListPreference(Context context) {
this(context, null);
}
@Override
protected void onPrepareDialogBuilder(Builder builder) {
CharSequence[] entries = getEntries();
CharSequence[] entryValues = getEntryValues();
if (entries == null || entryValues == null
|| entries.length != entryValues.length) {
throw new IllegalStateException(
"MultiSelectListPreference requires an entries array and an entryValues "
+ "array which are both the same length");
}
restoreCheckedEntries();
OnMultiChoiceClickListener listener = new DialogInterface.OnMultiChoiceClickListener() {
public void onClick(DialogInterface dialog, int which, boolean val) {
entryChecked[which] = val;
}
};
builder.setMultiChoiceItems(entries, entryChecked, listener);
}
private CharSequence[] unpack(CharSequence val) {
if (val == null || "".equals(val)) {
return new CharSequence[0];
} else {
return ((String) val).split(separator);
}
}
/**
* Gets the entries values that are selected
*
* @return the selected entries values
*/
public CharSequence[] getCheckedValues() {
return unpack(getValue());
}
private void restoreCheckedEntries() {
CharSequence[] entryValues = getEntryValues();
// Explode the string read in sharedpreferences
CharSequence[] vals = unpack(getValue());
if (vals != null) {
List<CharSequence> valuesList = Arrays.asList(vals);
for (int i = 0; i < entryValues.length; i++) {
CharSequence entry = entryValues[i];
entryChecked[i] = valuesList.contains(entry);
}
}
}
@Override
protected void onDialogClosed(boolean positiveResult) {
List<CharSequence> values = new ArrayList<CharSequence>();
CharSequence[] entryValues = getEntryValues();
if (positiveResult && entryValues != null) {
for (int i = 0; i < entryValues.length; i++) {
if (entryChecked[i] == true) {
String val = (String) entryValues[i];
values.add(val);
}
}
String value = join(values, separator);
setSummary(prepareSummary(values));
setValueAndEvent(value);
}
}
private void setValueAndEvent(String value) {
if (callChangeListener(unpack(value))) {
setValue(value);
}
}
private CharSequence prepareSummary(List<CharSequence> joined) {
List<String> titles = new ArrayList<String>();
CharSequence[] entryTitle = getEntries();
CharSequence[] entryValues = getEntryValues();
int ix = 0;
for (CharSequence value : entryValues) {
if (joined.contains(value)) {
titles.add((String) entryTitle[ix]);
}
ix += 1;
}
return join(titles, ", ");
}
@Override
protected Object onGetDefaultValue(TypedArray typedArray, int index) {
return typedArray.getTextArray(index);
}
@Override
protected void onSetInitialValue(boolean restoreValue,
Object rawDefaultValue) {
String value = null;
CharSequence[] defaultValue;
if (rawDefaultValue == null) {
defaultValue = new CharSequence[0];
} else {
defaultValue = (CharSequence[]) rawDefaultValue;
}
List<CharSequence> joined = Arrays.asList(defaultValue);
String joinedDefaultValue = join(joined, separator);
if (restoreValue) {
value = getPersistedString(joinedDefaultValue);
} else {
value = joinedDefaultValue;
}
setSummary(prepareSummary(Arrays.asList(unpack(value))));
setValueAndEvent(value);
}
/**
* Joins array of object to single string by separator
*
* Credits to kurellajunior on this post
* http://snippets.dzone.com/posts/show/91
*
* @param iterable
* any kind of iterable ex.: <code>["a", "b", "c"]</code>
* @param separator
* separetes entries ex.: <code>","</code>
* @return joined string ex.: <code>"a,b,c"</code>
*/
protected static String join(Iterable<?> iterable, String separator) {
Iterator<?> oIter;
if (iterable == null || (!(oIter = iterable.iterator()).hasNext()))
return "";
StringBuilder oBuilder = new StringBuilder(String.valueOf(oIter.next()));
while (oIter.hasNext())
oBuilder.append(separator).append(oIter.next());
return oBuilder.toString();
}
}
values-largeのエントリを使用してarray.xmlを定義したので同じエラーが発生しましたが、デフォルトのvaluesにファイルがありませんでしたパッケージ。したがって、私はarray.xmlをvaluesに移動しました。