11

有没有办法在只接受整数值的PreferenceFragment中创建首选项?我可以实现一个EditTextPreference并注册一个OnPreferenceChangeListener如果用户输入不是数字的字符串,我可以在其中拒绝更改,但我更喜欢仅用于保存数字并且不允许用户输入任何其他内容的东西, 可能只显示一个拨号盘键盘.. 我不存在这样的偏好,因为Preference的每个后代都映射到布尔值 ( CheckBoxPreference )、字符串 (*EditTextPreference) 或字符串数​​组 ( MultiSelectListPreference),即没有首选项映射到整数,但也许你们中的一些人可以给我一个提示,或者至少告诉我是否有比我上面提出的更好的解决方案。

Grey 提出的解决方案:

EditText editText = ((EditTextPreference)    
                             findPreference("intent_property")).getEditText();
editText.setKeyListener(new NumberKeyListener() {
    @Override
    public int getInputType() {
        // The following shows the standard keyboard but switches to the view 
        // with numbers on available on the top line of chars
        return InputType.TYPE_CLASS_NUMBER;
        // Return the following to show a dialpad as the one shown when entering phone
        // numbers.
        // return InputType.TYPE_CLASS_PHONE
    }

    @Override
    protected char[] getAcceptedChars() {
        return new String("1234567890").toCharArray();
    }
});

更短的解决方案,它不允许将键盘更改为拨号盘,但需要更少的代码:

EditText editText = ((EditTextPreference) 
                             findPreference("intent_property")).getEditText();
editText.setKeyListener(new DigitsKeyListener());

我不喜欢这个解决方案的一件事:用户可以输入 0000 并且它被接受并保存在共享首选项(这是一个字符串)中作为“0000”.. 这需要您实现 OnSharedPreferenceChangeListener 来拦截更改共享首选项并删除此首选项中的前导零或直接在此首选项上实现更改侦听器并返回 false 以拒绝带有尾随零的数字(告诉我是否有更好的解决方案来解决最后一个问题,不涉及实现您自己的首选项)。如果我们可以修改OnPreferenceChangeListener中的newValue那就太好了。

4

5 回答 5

32

有一种更简单的方法可以做到这一点。只需将 XML 中的 EditTextPreference 设置为 android:numeric="integer" (您可以将其设置为整数、有符号或小数)。

Eclipse(或您正在使用的任何工具)不会将其显示为可能的属性,而只需将其写入您的 EditTextPreference 并清理您的项目。你会看到它不会给你任何错误。:)

于 2012-12-07T10:45:20.550 回答
6

在阅读了建议的解决方案后,我仍然认为自定义偏好是要走的路。我确实以粗体字阅读了您的评论,但设置基本EditTextIntegerPreference功能实际上非常简单,它将解决您在用户输入例如“0000”时遇到的剩余问题。

只是预先说明:由于您通常希望能够在应用程序的多个位置使用首选项,因此就我而言,正确实现 anEditTextIntegerPreference会将其值存储在Integer. 这样您就可以在任何地方检索 int 值,而无需先解析或强制转换它。

但是,为了保持这个答案的重点和紧凑,我实际上将展示一个常规的扩展EditTextPreference,这意味着在引擎盖下,该值仍将存储为一个字符串。如果您真的热衷于让“正确”的实现发挥作用,我不介意稍后再写。不过,它不应该太棘手,因此您可能想先自己尝试一下。:)

public class EditTextIntegerPreference extends EditTextPreference {

    private Integer mInteger;

    public EditTextIntegerPreference(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        getEditText().setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED);
    }

    public EditTextIntegerPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        getEditText().setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED);
    }

    public EditTextIntegerPreference(Context context) {
        super(context);
        getEditText().setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED);
    }

    @Override public void setText(String text) {
        final boolean wasBlocking = shouldDisableDependents();
        mInteger = parseInteger(text);
        persistString(mInteger != null ? mInteger.toString() : null);
        final boolean isBlocking = shouldDisableDependents(); 
        if (isBlocking != wasBlocking) notifyDependencyChange(isBlocking);
    }

    @Override public String getText() {
        return mInteger != null ? mInteger.toString() : null;
    }

    private static Integer parseInteger(String text) {
        try { return Integer.parseInt(text); }
        catch (NumberFormatException e) { return null; }
    }    
}

这解决了“0000”问题的原因是,我们只是在存储之前将用户键入的值转换为 int,然后在检索时将其插入到字符串中。这意味着任何前导零(当然,“0”除外)都会自动消失。

'number' 输入类型将限制用户只能输入输入数字,因此该parseInteger(...)方法主要是出于理智的原因而存在,尽管NumberFormatException如果您尝试输入空字符串或null字符串,它会捕获 a。同样,你可以让它更漂亮,我现在还没有这样做。

于 2012-06-01T10:14:23.750 回答
1

我想你可以调用 getEditText() 来获取 EditText obj,然后用 NumberKeyListener 调用 setKeyListener。

于 2012-05-30T21:39:18.113 回答
1

您应该使用 PreferenceActivity,它基本上用于显示 xml 文件之类的首选项。在此活动中,您可以使用复选框、编辑文本并将值保存到首选项。

于 2013-04-18T11:31:20.640 回答
0

您也可以在尝试 parseInt() 数字后遇到异常时重新打开对话框。这是一个示例代码:

public class MyEditTextPreference extends EditTextPreference {

        private EditText _editText;

        public MyEditTextPreference(Context context, AttributeSet attrs) {
            super(context, attrs);
            _editText = getEditText();
        }

        @Override
        public void onDismiss(DialogInterface dialog) {

            super.onDismiss(dialog);

            try {
                Integer.parseInt(_editText.getText().toString());
            } catch (NumberFormatException e) {

                ((Dialog) dialog).show();
            }
        }
    }
于 2014-01-17T19:30:42.770 回答