Получение целых или индексных значений из предпочтений списка
Я создаю списки с общим предпочтением и когда вызывается метод onPreferenceChanged(), я хочу в какой-то момент извлечь индекс элемента в списке или целочисленное значение. Я пытаюсь создать XML-данные следующим образом:
в массивах:
<string-array name="BackgroundChoices">
<item>Dark Background</item>
<item>Light Background</item>
</string-array>
<array name="BackgroundValues">
<item>1</item>
<item>0</item>
</array>
<string-array name="SpeedChoices">
<item>Slow</item>
<item>Medium</item>
<item>Fast</item>
</string-array>
<array name="SpeedValues">
<item>1</item>
<item>4</item>
<item>16</item>
</array>
в файле настроек xml:
<PreferenceScreen android:key="Settings"
xmlns:android="http://schemas.android.com/apk/res/android"
android:title="Settings">
<ListPreference
android:key="keyBackground"
android:entries="@array/BackgroundChoices"
android:summary="Select a light or dark background."
android:title="Light or Dark Background"
android:positiveButtonText="Okay"
android:entryValues="@array/BackgroundValues"/>
<ListPreference
android:key="keySpeed"
android:entries="@array/SpeedChoices"
android:summary="Select animation speed."
android:title="Speed" android:entryValues="@array/SpeedValues"/>
</PreferenceScreen>
Итак, мой xml не работает. Я знаю, как это сделать, используя строковый массив, а не массив для значений. И я мог бы вытащить строки значений и получить то, что хочу от этого, но я предпочел бы (если возможно) иметь списки, в которых значения были бы ints, booleans или перечислениями. Каков обычный способ сделать это?
спасибо заранее,
Джей
Ответы
Ответ 1
Поместите настройки в качестве String
и используйте Integer.parseInt()
. Я думаю, что на самом деле есть отчет об ошибке, на который вы ссылаетесь, но я не могу найти ссылку. Из опыта я могу сказать вам просто использовать Strings
и сэкономить себе много разочарования.
Обратите внимание на других пользователей SO, если вы можете доказать свою несостоятельность, я приветствую это.
Ответ 2
Андрей был прав, поток здесь:
он все еще прокомментирован, и все же никаких изменений (по 2.3.3 в любом случае).
Integer.parseInt().valueOf() должен работать. Если функция valueOf() работает без ошибок, используйте ее, поскольку она не выделяет столько, сколько используется parseInt(), когда вам НЕОБХОДИМО избегать GC, как я.
Ответ 3
Основываясь на Android ListPreference, я создал IntListPreference. Использование - слишком просто - просто поместите этот фрагмент в свои предпочтения xml:
<org.bogus.android.IntListPreference
android:key="limitCacheLogs"
android:defaultValue="20"
android:entries="@array/pref_download_logs_count_titles"
android:entryValues="@array/pref_download_logs_count_values"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:title="@string/pref_download_logs_count"
/>
и что в strings.xml
<string name="pref_download_logs_count">Number of logs per cache</string>
<string-array name="pref_download_logs_count_titles">
<item>10</item>
<item>20</item>
<item>50</item>
<item>Give me all!</item>
</string-array>
<integer-array name="pref_download_logs_count_values">
<item>10</item>
<item>20</item>
<item>50</item>
<item>-1</item>
</integer-array>
Ответ 4
Здесь используется класс ListIntegerPreference
, который используется (написан для com.android.support:preference-v7:24.0.0
). Он перезаписывает несколько методов и конвертирует между Integer
и String
, где это возможно, так что база ListPreference
не распознает, что вы работаете с Integers
вместо Strings
.
public class ListIntegerPreference extends ListPreference
{
public ListIntegerPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
{
super(context, attrs, defStyleAttr, defStyleRes);
}
public ListIntegerPreference(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
}
public ListIntegerPreference(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public ListIntegerPreference(Context context)
{
super(context);
}
@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue)
{
int defValue = defaultValue != null ? Integer.parseInt((String)defaultValue) : 0;
int value = getValue() == null ? 0 : Integer.parseInt(getValue());
this.setValue(String.valueOf(restoreValue ? this.getPersistedInt(value) : defValue));
}
@Override
public void setValue(String value)
{
try
{
Field mValueField = ListPreference.class.getDeclaredField("mValue");
mValueField.setAccessible(true);
Field mValueSetField = ListPreference.class.getDeclaredField("mValueSet");
mValueSetField.setAccessible(true);
String mValue = (String)mValueField.get(this);
boolean mValueSet = (boolean)mValueSetField.get(this);
boolean changed = !TextUtils.equals(mValue, value);
if(changed || !mValueSet)
{
mValueField.set(this, value);
mValueSetField.set(this, mValueSet);
this.persistInt(Integer.parseInt(value));
if(changed) {
this.notifyChanged();
}
}
}
catch (NoSuchFieldException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
}
}
Я использую это с созданием значений ListPreferences
через код, просто попробуйте. Это может сработать сразу, или, возможно, вам нужно переопределить дополнительные функции. Если это так, это хорошее начало и показывает вам, как вы можете это сделать...