我正在尝试创建一个数字选择器来选择一个月。 只要我通过滚动选择值,或者如果我使用键盘输入月份文本(例如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,但这并没有改变任何内容。
如果我尝试输入数字,编辑文字将保持为空。
答案 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());
}
}