有没有人知道使用Android默认的numberpicker允许负数的简单方法?我知道它是不允许这样做的InputFilter,但有没有简单的方法可以覆盖而不重写整个小部件?
答案 0 :(得分:14)
更通用和更优雅的解决方案是使用NumberPicker.Formatter并在NumberPicker中仅使用正数。
如果我想在[-50,50]中选择一个数字的示例:
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);
}
});
然后返回所选值:
int myNewValue = numberPicker.getValue() + minValue
答案 1 :(得分:5)
使用:
String[] nums {"-1","-2","-3","-4"};
numberpicker.setDisplayedValues(nums);
或
String[] nums = new String[4];
for(int i=0; i<nums.length; i++)
nums[i] = "-" + Integer.toString(i);
numberpicker.setDisplayedValues(nums);
其中任何一个都允许您为NumberPicker使用任何字符串集。你正在做的是你指定一组字符串,你传递给NumberPicker。然后它将显示您的值而不是默认值。
答案 2 :(得分:1)
使用.setFormatter()
不允许输入负数。使用.setDisplayedValues()
时,键盘显示为文本而非数字。
所以这是课程SignedNumberPicker
:
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()
,而charPase(!?)在内部使用beacuse getValue()
。
我还添加了setOnTextFocusChangedListener()
方法,这可能方便了禁用OK按钮等。
更新: 如果您想阻止用户输入相同的值,只要显示键盘就可以禁用“确定”按钮,并听取值更改:
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);
}
});
答案 3 :(得分:-1)
Here是您正在寻找的示例。
private static final int DEFAULT_MAX = 200;
private static final int DEFAULT_MIN = 0;// change this acc to your requirement