ListPreference:使用string-array作为Entry和integer-array作为Entry Values不起作用

San*_*rab 69 android listpreference

我在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)
Run Code Online (Sandbox Code Playgroud)

这是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" />
Run Code Online (Sandbox Code Playgroud)

以下是我用来填充条目的数组:

<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>
Run Code Online (Sandbox Code Playgroud)

在我的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;
        }
}
Run Code Online (Sandbox Code Playgroud)

如果我为entryValues使用另一个字符串数组,它可以工作.例如,如果我使用相同的字符串数组作为值和条目:

    android:entries="@array/date_alignement"
    android:entryValues="@array/date_alignement"
Run Code Online (Sandbox Code Playgroud)

然后我必须稍微改变我的代码,但它的工作原理:

        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;
        }
Run Code Online (Sandbox Code Playgroud)

为什么我不能对ListPreference条目和值使用字符串数组和整数数组?

Ego*_*gor 83

答案很简单:因为Android是这样设计的.它只是String为条目和条目值使用数组,这就是全部.而且我在这个事实中看不出任何问题,因为您可以轻松地将a转换Stringint使用该Integer.parseInt()方法.希望这可以帮助.

  • 好的,仍然不明白为什么它不受支持.显然我可以和我将它转换,但如果可以使用特定的结构(整数数组)而不是使用字符串一并将其转换为int,它应该工作:)无论如何,谢谢! (27认同)
  • @Egor这是一个愚蠢的原因.当然,您应该能够存储不同的基本类型.您甚至可以将对象类型序列化为.Net中的配置.这不是一个大混乱. (19认同)
  • 我遇到了同样的问题.很容易让`ListPreference`回复整数.请参阅:http://kvance.livejournal.com/1039349.html (12认同)
  • @Santacrab,如果有一个整数数组支持,那么也应该有float数组支持,double,char等.这将是一个很大的混乱,所以我认为将String转换为你需要的任何数据类型更容易.如果您发现它有用,请接受答案. (3认同)
  • @thom_nic 那个 livejournal 链接似乎已经死了 (3认同)
  • 实际上存在整数数组结构。问题是当与字符串一配对时它不起作用。 (2认同)
  • `答案很简单:因为Android是这样设计的`你是在告诉我android是严格设计的吗?对不起,这可能是一个蹩脚的借口,但不是答案! (2认同)

Sam*_*Sam 8

您可以将条目值转换为字符串以保持ListPreference满意,然后int在与持久数据存储通信时将它们转换为 s。

  1. 设置条目值时,使用字符串而不是整数:"1", "2", "3"
  2. 进行自定义IntListPreference以将值保留为整数
  3. 在您的preferences.xml文件中,将 更改<ListPreference><your.app.package.IntListPreference>

IntListPreference.java

这是一个示例实现。已在 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);
    }

}
Run Code Online (Sandbox Code Playgroud)