【问题标题】:android numberpicker can't read keyboard number inputandroid numberpicker无法读取键盘数字输入
【发布时间】:2015-03-28 20:00:42
【问题描述】:

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

我还希望我的用户能够输入“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 只是保持为空。 这就是我初始化我的数字选择器的方式:

    //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 给出的答案将编辑文本的输入类型设置为 InputType.TYPE_NULL,但这并没有改变任何东西。

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

【问题讨论】:

    标签: android numberpicker


    【解决方案1】:

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

    我通过从 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;
    }
    

    【讨论】:

      【解决方案2】:

      只是为了详细说明这一点,这是我为获取 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());
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-09-18
        • 1970-01-01
        • 1970-01-01
        • 2023-03-29
        • 2013-10-25
        • 2013-01-30
        • 1970-01-01
        相关资源
        最近更新 更多