如何创建仅接受整数值的首选项

时间:2012-05-30 21:29:11

标签: android android-edittext android-preferences

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

格雷提出的解决方案:

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 那将是美好的。

5 个答案:

答案 0 :(得分:31)

有一种更简单的方法可以做到这一点。只需在XML中的EditTextPreference中设置android:numeric =“integer”(可以将其设置为整数,有符号或十进制)。

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

答案 1 :(得分:6)

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

前面的说明:因为您通常希望能够在应用中的多个位置使用偏好设置,就我而言,正确实施EditTextIntegerPreference会将其值存储在应用中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'作为课程数量)将自动消失。

“数字”输入类型将限制用户仅输入输入数字,因此{1}}方法主要出于理智原因,但如果您尝试输入parseInteger(...),则会捕获NumberFormatException空或null字符串。再说一次,你可以让它变得更漂亮,我现在还没有这样做。

答案 2 :(得分:1)

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

答案 3 :(得分:1)

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

答案 4 :(得分: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();
            }
        }
    }
相关问题