Подтвердить что ты не робот

Получение целых или индексных значений из предпочтений списка

Я создаю списки с общим предпочтением и когда вызывается метод 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 или перечислениями. Каков обычный способ сделать это?

спасибо заранее,

Джей

4b9b3361

Ответ 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 через код, просто попробуйте. Это может сработать сразу, или, возможно, вам нужно переопределить дополнительные функции. Если это так, это хорошее начало и показывает вам, как вы можете это сделать...