【问题标题】:Change the step size of a NumberPicker更改 NumberPicker 的步长
【发布时间】:2012-10-10 09:16:27
【问题描述】:

是否有可能比在 OnScrollListener 事件中处理更方便?可惜它没有步长属性...

【问题讨论】:

    标签: android android-widget


    【解决方案1】:

    Android 中的 NumberPicker 有一个名为 setDisplayedValues 的方法。 您可以使用它来显示自定义值(它需要一个字符串数组),然后在需要值时映射它们。 因此,例如,如果您在一分钟选择器中需要 5 步,您可以创建一个这样的数组:

    String[] minuteValues = new String[12];
    
    for (int i = 0; i < minuteValues.length; i++) {
        String number = Integer.toString(i*5);
        minuteValues[i] = number.length() < 2 ? "0" + number : number;
    }
    
    minutePicker.setDisplayedValues(minuteValues);
    

    然后当你得到OnValueChangeListener中的值时,你只需要把它转换回一个整数:

    Integer.parseInt(minuteValues[newVal]);
    

    【讨论】:

    • 请注意,Android 按从上到下的升序显示自定义值。您可能想通过将i*5 替换为55-i*5 来扭转它
    【解决方案2】:

    例如,要将步数设置为“5”,请使用NumberPicker.Formatter

        NumberPicker.Formatter formatter = new NumberPicker.Formatter() {
            @Override
            public String format(int value) {
                int temp = value * 5;
                return "" + temp;
            }
        };
        numberPicker.setFormatter(formatter);
    

    【讨论】:

    • 其实这个解决方案很简单但同时也很棘手,我可能更喜欢这种方式
    • 不要忘记将 numberPicker.setMaxValue 设置为合理的值。如果您根本不设置它,则选择器将只显示 0。例如,以 5 分钟为增量的一小时,您必须将其设置为 11,因为选择器将保存 11 个数字(0 - 55)。跨度>
    • 设置 numberPicker.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);否则选择器中的数字字段将能够成为输入焦点。
    • @ckn 然后在滚动之前不会显示初始数字!它通常不显示,但会调出键盘进行输入。有什么解决办法吗?
    【解决方案3】:

    为什么不添加OnValueChangeListener 类似的东西:

    numberPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
    
         @Override
         public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
             picker.setValue((newVal < oldVal)?oldVal-5:oldVal+5);
         }
    
    });
    

    【讨论】:

    • 好的,但这就像使用 onScrollListener 一样。使用事件是实现这种效果的唯一方法吗?
    • 是的,我想您可以将类扩展为具有步长,然后覆盖 onClick 方法。不过,这可能比仅使用侦听器要多一些代码。
    • 监听方法应该是onValueChange而不是onChange,setter现在应该是setOnValueChangedListener。
    【解决方案4】:

    Android 中的 NumberPicker 有一个名为 setDisplayedValues 的方法。您可以使用它来显示自定义值(它需要一个字符串数组),然后在需要值时映射它们。

    例如,您可以创建这样的函数:

    public String[] getArrayWithSteps (int iMinValue, int iMaxValue, int iStep)
    { 
       int iStepsArray = (iMaxValue-iMinValue) / iStep+1; //get the lenght array that will return
    
       String[] arrayValues= new String[iStepsArray]; //Create array with length of iStepsArray 
    
       for(int i = 0; i < iStepsArray; i++)
       {
         arrayValues[i] = String.valueOf(iMinValue + (i * iStep));
       }
    
       return arrayValues;
    }
    

    所以,你应该调用方法>NumberPicker.setDisplayedValues,例如:

    int min = 5;
    int max = 180;
    int step = 10;
    
    String[] myValues = getArrayWithSteps(min, max, step); //get the values with steps... Normally 
    
    //Setting the NumberPick (myNumberPick)
    myNumberPick.setMinValue(0);
    myNumberPick.setMaxValue((max-step) / min + 1); //Like iStepsArray in the function
    //Because the Min and Max Value should be the range that will show. 
    //For example, Min = 0 and Max = 2, so the NumberPick will display the first three strings in the array String (myValues); 
    myNumberPick.setDisplayedValues(myValues);//put on NumberPicker 
    

    获取 NumberPick 中的值:

    String sValue = String.valueOf(10+(myNumberPick.getValue()*5)); //->> (iMinValue + (myNumberPick.getValue()*iStep))
    

    【讨论】:

    • myNumberPick.setMaxValue((max-step)/min+1); //像函数中的iStepsArray 最好是: (max-min)/step. - 最小值可能为 0,除以 0 是错误的。 - 没有 +1,因为你会增加 1 个值
    【解决方案5】:

    使用上述方法时,需要注意选择器不仅允许用户通过滚动选择值,还可以通过键盘输入。

    默认情况下,输入字段的输入类型设置为TYPE_CLASS_NUMBER,因此用户会看到数字键盘。似乎当您使用setDisplayedValues 时,选择器会将类型更改为TYPE_CLASS_TEXT,但是,当您使用setFormatter 时,输入类型不会更改。

    因此,在这种情况下使用格式化程序可能会导致意外行为。假设您希望用户只能选择值“0”或“5”。你可能有这样的代码:

    NumberPicker numberPicker = (NumberPicker) findViewById(R.id.my_number_picker);
    numberPicker.setMinValue(0);
    numberPicker.setMaxValue(1);
    numberPicker.setFormatter(v -> v == 0 ? "0" : "5");
    

    但是,在这种情况下,用户会看到数字键盘,但只能输入“0”或“1”。

    如果你改用:

    numberPicker.setDisplayedValues(new String[] { "0", "5" });
    

    用户将看到文本键盘,但可以按预期输入“0”或“5”。

    如果您对文本键盘感到困扰,您可以使用反射来访问私有字段并将输入类型设置回数字(除非确实必要,否则当然不建议这样做)。该字段称为“mInputText”,如果您针对 Gingerbread 等老歌迷,该字段称为“mText”。

        try {
            Field inputField = NumberPicker.class.getDeclaredField("mInputText");
            inputField.setAccessible(true);
    
            EditText inputText = (EditText) inputField.get(numberPicker);
            inputText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
        } catch (ClassCastException e) {
            // Just ignore this exception and do nothing.
        } catch (IllegalAccessException e) {
            // Just ignore this exception and do nothing.
        } catch (NoSuchFieldException e) {
            // Just ignore this exception and do nothing.
        }
    

    【讨论】:

      【解决方案6】:

      这是 ajpolt 解决方案的更好方法

      具有任何预定义的步长,它支持通过键盘设置自定义值。

       final NumberPicker np = (NumberPicker) dialogView.findViewById(R.id.numberPicker1);
          np.setMaxValue(1000); // max value 1000
          np.setMinValue(0);   // min value 0
          np.setValue(defValue);
          np.setWrapSelectorWheel(false);
          final int m_oldFocus = np.getDescendantFocusability();
          np.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
          np.setOnTouchListener(new View.OnTouchListener() {
              @Override
              public boolean onTouch(View view, MotionEvent motionEvent) {
                  np.setDescendantFocusability(m_oldFocus);
                  return false;
              }
          });
      
          np.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
              @Override
              public void onValueChange(NumberPicker numberPicker, int oldVal, int newVal) {
                  int stepSize = 10;
                  if(newVal%stepSize !=0){
                      if(newVal < oldVal){
                          numberPicker.setValue(((int)(newVal/stepSize)) *stepSize);
                      }else{
                          numberPicker.setValue((((int)(newVal/stepSize)) *stepSize ) +stepSize );
                      }
      
                  }else{
                      numberPicker.setValue(newVal);
                  }
      
              }
          });
      

      *我知道这是 5 年前的问题,但可能对某人有用

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-15
        • 1970-01-01
        • 2019-01-05
        • 2014-05-22
        • 1970-01-01
        • 2016-03-06
        • 2012-11-25
        相关资源
        最近更新 更多