首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何创建负NumberPicker

如何创建负NumberPicker
EN

Stack Overflow用户
提问于 2013-01-16 19:37:02
回答 4查看 6.6K关注 0票数 9

有没有人知道用Android的默认数字选择器来允许负数的简单方法?我知道这是InputFilter不允许的,但是有什么简单的方法可以在不重写整个小部件的情况下覆盖它吗?

EN

回答 4

Stack Overflow用户

发布于 2013-07-17 20:17:12

一种更通用、更优雅的解决方案是使用NumberPicker.Formatter,并在NumberPicker中仅使用正数。

例如,如果我想选择- 50,50中的一个数字

代码语言:javascript
复制
final int minValue = -50
final int maxValue = 50
NumberPicker numberPicker = new NumberPicker(myActivity);
numberPicker.setMinValue(0);
numberPicker.setMaxValue(maxValue - minValue);
numberPicker.setValue(myCurrentValue - minValue);
numberPicker.setFormatter(new NumberPicker.Formatter() {
    @Override
    public String format(int index) {
        return Integer.toString(index + minValue);
    }
});

然后,要取回选定的值:

代码语言:javascript
复制
int myNewValue = numberPicker.getValue() + minValue
票数 14
EN

Stack Overflow用户

发布于 2013-02-25 00:04:13

使用:

代码语言:javascript
复制
String[] nums {"-1","-2","-3","-4"};
numberpicker.setDisplayedValues(nums);

代码语言:javascript
复制
String[] nums = new String[4];
for(int i=0; i<nums.length; i++)
nums[i] = "-" + Integer.toString(i);
numberpicker.setDisplayedValues(nums);

这两种方法中的任何一种都可以让你在NumberPicker中使用任意一组字符串。您要做的是指定一组字符串,然后将这些字符串传递给NumberPicker。然后,它将显示您的值,而不是默认值。

票数 5
EN

Stack Overflow用户

发布于 2018-03-27 03:25:07

使用.setFormatter()不允许输入负数。使用.setDisplayedValues()时,键盘显示为文本而不是数字。下面是SignedNumberPicker

代码语言:javascript
复制
class SignedNumberPicker extends android.widget.NumberPicker {
  int nToAdd=0,mMaxValue=0,mMinValue=0;
  EditText tv;
  private void init() {
    super.setFormatter(new Formatter() {
      @Override
      public String format(int i) {
        int r=i-nToAdd;
        return String.valueOf(r);
      }
    });
    tv.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED);
    tv.setFilters(new InputFilter[] {new InputTextFilter()});
    tv.setOnFocusChangeListener(new OnFocusChangeListener() {
      @Override
      public void onFocusChange(View view, boolean b) {
        if (b) {
          tv.selectAll();
        } else {
          String str = String.valueOf(((EditText) view).getText());
          if (TextUtils.isEmpty(str.replace("-",""))) {
            tv.setText(String.valueOf(getRealValue()));
          } else {
            textToValue();
          }
          InputMethodManager keyboard = (InputMethodManager) getContext().getSystemService(Context
              .INPUT_METHOD_SERVICE);
          if (keyboard != null) {
            keyboard.hideSoftInputFromWindow(tv.getWindowToken(),0);
          }
          tv.setVisibility(INVISIBLE);
        }
        if (mOnTextFocusChangedListener!=null) {
          mOnTextFocusChangedListener.onTextFocusChanged(b);
        }
      }
    });
  }
  void textToValue() {
    try {
      setValue(Integer.valueOf(tv.getText().toString()));
    } catch (Exception e) {}
  }
  OnTextFocusChangedListener mOnTextFocusChangedListener =null;
  public interface OnTextFocusChangedListener {
    void onTextFocusChanged(boolean textViewHasFocus);
  }
  public void setOnTextFocusChangedListener(OnTextFocusChangedListener l) {
    mOnTextFocusChangedListener =l;
  }
  public SignedNumberPicker(Context context) {
    super(context);
    init();
  }
  public SignedNumberPicker(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
  }
  @Override
  public void addView(View child) {
    super.addView(child);
    init(child);
  }
  @Override
  public void addView(View child, int index, android.view.ViewGroup.LayoutParams params) {
    super.addView(child, index, params);
    init(child);
  }
  @Override
  public void addView(View child, android.view.ViewGroup.LayoutParams params) {
    super.addView(child, params);
    init(child);
  }
  private void init(View view) {
    if(view instanceof EditText){
      tv=((EditText) view);
    }
  }

  @Override
  public void setMinValue(int minValue) {
    if (minValue<0) {
      nToAdd=-minValue;
      super.setMaxValue(super.getMaxValue()+nToAdd);
    }
    mMinValue=minValue;
    super.setMinValue(minValue+nToAdd);
  }

  @Override
  public void setMaxValue(int maxValue) {
    if (maxValue+nToAdd<0) {
      nToAdd=-maxValue;
    }
    mMaxValue=maxValue;
    super.setMaxValue(maxValue+nToAdd);
  }

  @Override
  public void setValue(int value) {
    super.setValue(value+nToAdd);
  }
  public int getRealValue() {
    if (tv.hasFocus()) textToValue();
    return super.getValue()-nToAdd;
  }
  private NumberPicker.OnValueChangeListener mOnValueChangedListener=null;
  @Override
  public void setOnValueChangedListener(OnValueChangeListener onValueChangedListener) {
    mOnValueChangedListener=onValueChangedListener;
    super.setOnValueChangedListener(new OnValueChangeListener() {
      @Override
      public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
        mOnValueChangedListener.onValueChange(picker,oldVal-nToAdd,newVal-nToAdd);
      }
    });
  }

  //copied from NumberPicker source & modified
  //https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/widget/NumberPicker.java
  class InputTextFilter extends NumberKeyListener {

    // 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) {
      // We don't know what the output will be, so always cancel any
      // pending set selection command.
      /*if (mSetSelectionCommand != null) {
        mSetSelectionCommand.cancel();
      }*/
      //and we will ignore this

      CharSequence filtered = super.filter(source, start, end, dest, dstart, dend);
      if (filtered == null) {
        filtered = source.subSequence(start, end);
      }

      String result = String.valueOf(dest.subSequence(0, dstart)) + filtered
          + dest.subSequence(dend, dest.length());

      if ("".equals(result)) {
        return result;
      }
      int val = getSelectedPos(result);

    /*
     * Ensure the user can't type in a value greater than the max
     * allowed. We have to allow less than min as the user might
     * want to delete some numbers and then type a new number.
     * And prevent multiple-"0" that exceeds the length of upper
     * bound number.
     */
      if (val > mMaxValue || (result.length() > String.valueOf(mMaxValue).length() && result
          .length()>String.valueOf(mMinValue).length()) || (val<0 && val<mMinValue)) {
        return "";
      } else {
        return filtered;
      }
    }
    private int getSelectedPos(String value) {
      try {
        return Integer.parseInt(value);
      } catch (NumberFormatException e) {
        // Ignore as if it's not a number we don't care
      }
      return mMinValue;
    }
    private final char[] DIGIT_CHARACTERS = new char[] {
        //THE MINUS SIGN
        '-',
        // 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'
    };
  }
}

像“普通”NumberPicker一样使用它,但可以随意使用负数。不使用getValue(),而使用getRealValue(),因为NumberPicker (!?)在内部使用getValue()。我还添加了setOnTextFocusChangedListener()方法,它可以方便地禁用OK按钮等。

更新:如果你想阻止用户输入相同的值,只要键盘显示,你就可以禁用OK按钮,并监听数值变化:

代码语言:javascript
复制
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
numberPicker.setOnTextFocusChangedListener(new SignedNumberPicker.OnTextFocusChangedListener() {
  @Override
  public void onTextFocusChanged(boolean textViewHasFocus) {
    if (textViewHasFocus) {
      dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
    } else {
      dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(numberPicker.getRealValue()!=currentValue);
    }
  }
});
numberPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
  @Override
  public void onValueChange(android.widget.NumberPicker picker, int oldVal, int newVal) {
    dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(newVal!=currentValue);
  }
});
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14357520

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档