android numberpicker无法读取键盘数字输入

时间:2015-01-29 14:38:51

标签: android numberpicker

我正在尝试创建一个数字选择器来选择一个月。 只要我通过滚动选择值,或者如果我使用键盘输入月份文本(例如januari的“jan”),它就可以工作

我也希望我的用户能够输入'1'来选择januari。 从numberpicker源代码看,这应该是可能的:

/**
 * @return The selected index given its displayed <code>value</code>.
 */
private int getSelectedPos(String value) {
    if (mDisplayedValues == null) {
        try {
            return Integer.parseInt(value);
        } catch (NumberFormatException e) {
            // Ignore as if it's not a number we don't care
        }
    } else {
        for (int i = 0; i < mDisplayedValues.length; i++) {
            // Don't force the user to type in jan when ja will do
            value = value.toLowerCase();
            if (mDisplayedValues[i].toLowerCase().startsWith(value)) {
                return mMinValue + i;
            }
        }

        /*
         * The user might have typed in a number into the month field i.e.
         * 10 instead of OCT so support that too.
         */
        try {
            return Integer.parseInt(value);
        } catch (NumberFormatException e) {

            // Ignore as if it's not a number we don't care
        }
    }
    return mMinValue;
}

问题是,如果我尝试输入一个数字,EditText就会保持为空。 这是我初始化我的numberpicker的方式:

    //getting the months using Calendar
    Calendar cal = Calendar.getInstance();
    Map<String, Integer> monthMap = cal.getDisplayNames(Calendar.MONTH, Calendar.LONG, Locale.getDefault());
    TreeMap<Integer, String> sorted = new TreeMap<>();
    for(Map.Entry<String, Integer> entry : monthMap.entrySet()) {
        sorted.put(entry.getValue(), entry.getKey());
    }

    String[] displayNames = sorted.values().toArray(new String[]{});

    mMonthPicker.setMinValue(0);
    mMonthPicker.setMaxValue(11);
    mMonthPicker.setDisplayedValues(displayNames);
    mMonthPicker.setWrapSelectorWheel(false);

我尝试使用给定here的答案将edittext的inputtype设置为InputType.TYPE_NULL,但这并没有改变任何内容。

如果我尝试输入数字,编辑文字将保持为空。

2 个答案:

答案 0 :(得分:0)

我终于明白了。由于EditText上的过滤器,numberpicker不允许输入月份数字。

我通过从numberpicker源代码复制NumberKeyListener的一些代码并调整它以便接受数字输入来解决它。

然后我在EditText上添加了这个过滤器,我通过查看子视图并检查当前视图是否为EditText来查找。 我在答案中找到了查找EditText的代码:NumberPicker doesn't work with keyboard

我的代码如下:

mInputText = findInput(mMonthPicker);
mInputText.setFilters(new InputFilter[]{ new InputTextFilter() });

这是我的过滤器:

/**
 * Filter for accepting only valid indices or prefixes of the string
 * representation of valid indices.
 */
class InputTextFilter extends NumberKeyListener {

    /**
     * The numbers accepted by the input text's {@link android.view.LayoutInflater.Filter}
     */
   private final char[] DIGIT_CHARACTERS = new char[] {
            // Latin digits are the common case
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            // Arabic-Indic
            '\u0660', '\u0661', '\u0662', '\u0663', '\u0664', '\u0665', '\u0666', '\u0667', '\u0668'
            , '\u0669',
            // Extended Arabic-Indic
            '\u06f0', '\u06f1', '\u06f2', '\u06f3', '\u06f4', '\u06f5', '\u06f6', '\u06f7', '\u06f8'
            , '\u06f9',
            // Hindi and Marathi (Devanagari script)
            '\u0966', '\u0967', '\u0968', '\u0969', '\u096a', '\u096b', '\u096c', '\u096d', '\u096e'
            , '\u096f',
            // Bengali
            '\u09e6', '\u09e7', '\u09e8', '\u09e9', '\u09ea', '\u09eb', '\u09ec', '\u09ed', '\u09ee'
            , '\u09ef',
            // Kannada
            '\u0ce6', '\u0ce7', '\u0ce8', '\u0ce9', '\u0cea', '\u0ceb', '\u0cec', '\u0ced', '\u0cee'
            , '\u0cef'
    };

    // XXX This doesn't allow for range limits when controlled by a
    // soft input method!
    public int getInputType() {
        return InputType.TYPE_CLASS_TEXT;
    }

    @Override
    protected char[] getAcceptedChars() {
        return DIGIT_CHARACTERS;
    }

    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        Log.v("filter", "source:" + source.toString());

        CharSequence filtered = String.valueOf(source.subSequence(start, end));

        Log.v("filter", "filtered:" + filtered.toString());
        if (TextUtils.isEmpty(filtered)) {
            return "";
        }
        String result = String.valueOf(dest.subSequence(0, dstart)) + filtered
                + dest.subSequence(dend, dest.length());
        String str = String.valueOf(result).toLowerCase();
        try{
            int value = Integer.parseInt(str);

            if(1 <= value && value <= 12) {
                return source;
            }
        } catch(NumberFormatException e) {
            //continue with the checking
        }

        for (String val : mMonthPicker.getDisplayedValues()) {
            String valLowerCase = val.toLowerCase();
            if (valLowerCase.startsWith(str)) {
                final int selstart = result.length();
                final int selend = val.length();
                mInputText.post(new Runnable() {
                    @Override
                    public void run() {
                        mInputText.setSelection(selstart, selend);
                    }
                });
                return val.subSequence(dstart, val.length());
            }
        }
        return "";

    }
}

这是找到EditText的代码:

private EditText findInput(ViewGroup np) {
    int count = np.getChildCount();
    for (int i = 0; i < count; i++) {
        final View child = np.getChildAt(i);
        if (child instanceof ViewGroup) {
            findInput((ViewGroup) child);
        } else if (child instanceof EditText) {
            return (EditText) child;
        }
    }
    return null;
}

答案 1 :(得分:0)

只是详细说明一下,这是我为获取EditText输入值所做的工作(扩展了SnyersK代码)。自定义编辑文本也可以设置为禁用键盘输入,并在xml中具有最小值和最大值:

xml使用:

<com.octane.smartlink.widgets.SmartLinkNumberPicker
    android:id="@+id/distance_tenths_of_distance"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    max="9"
    min="0"/>

Android小部件类:

public class SmartLinkNumberPicker extends NumberPicker { 

    //declare needed variables
    private EditText numberEditText;
    private boolean shouldDisableEditText = true; //set to true to disable edit text input and focus

    public SmartLinkNumberPicker(Context context) {
        super(context);
    }

    public SmartLinkNumberPicker(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    public SmartLinkNumberPicker(Context context, AttributeSet attrs, int   defStyle) {
        super(context, attrs, defStyle);
        init(attrs);
    }

    private void init(AttributeSet attrs) {
        numberEditText = populateEditText((ViewGroup) this);
        if(numberEditText != null && shouldDisableEditText)
            numberEditText.setFocusable(false);
        processAttributeSet(attrs);
    }

    private EditText populateEditText(ViewGroup viewGroup) {        
        int count = viewGroup.getChildCount();
        for(int i = 0; i < count; i++) {
            final View child = viewGroup.getChildAt(i);
            if (child instanceof ViewGroup)
                populateEditText((ViewGroup) child);
            else if (child instanceof EditText)
                return (EditText) child;
        }

        return null;
    }

    /*
     * used to set min, max attributes in xml 
     * set by min = "0" and max = "9" 
     */
    private void processAttributeSet(AttributeSet attrs) {
        this.setMinValue(attrs.getAttributeIntValue(null, "min", 0));
        this.setMaxValue(attrs.getAttributeIntValue(null, "max", 0));
    }

    /*
     * always returns a valid number since number input is only allowed
     * this will capture value set by either plus/minus buttons or edit text input
     */
    @Override
    public int getValue() {
        return Integer.valueOf(numberEditText.getEditableText().toString());
    }

}