我写了这个TextWatcher
对于一个项目,希望对某人有帮助。请注意,它确实not验证用户输入的日期,并且您应该在焦点更改时处理该问题,因为用户可能尚未完成输入日期。
更新 25/06将其设为 wiki,看看我们是否能得到更好的最终代码。
更新07/06我最终为观察者本身添加了某种验证。它将对无效日期执行以下操作:
- 如果月份大于 12,则为 12(12 月)
- 如果该日期大于所选月份的日期,请将其设为该月的最大值。
- 如果年份不在范围内
1900-2100
,将其更改为范围内
此验证符合我的需求,但你们中的一些人可能想稍微更改一下,范围很容易更改,您可以将此验证挂钩到Toast
例如,消息通知用户我们已经修改了他/她的日期,因为它是无效的。
在这段代码中,我假设我们引用了我们的EditText
called date
有这个TextWatcher
附加到它,可以这样做:
EditText date;
date = (EditText)findViewById(R.id.whichdate);
date.addTextChangedListener(tw);
TextWatcher tw = new TextWatcher() {
private String current = "";
private String ddmmyyyy = "DDMMYYYY";
private Calendar cal = Calendar.getInstance();
当用户更改文本时EditText
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (!s.toString().equals(current)) {
String clean = s.toString().replaceAll("[^\\d.]|\\.", "");
String cleanC = current.replaceAll("[^\\d.]|\\.", "");
int cl = clean.length();
int sel = cl;
for (int i = 2; i <= cl && i < 6; i += 2) {
sel++;
}
//Fix for pressing delete next to a forward slash
if (clean.equals(cleanC)) sel--;
if (clean.length() < 8){
clean = clean + ddmmyyyy.substring(clean.length());
}else{
//This part makes sure that when we finish entering numbers
//the date is correct, fixing it otherwise
int day = Integer.parseInt(clean.substring(0,2));
int mon = Integer.parseInt(clean.substring(2,4));
int year = Integer.parseInt(clean.substring(4,8));
mon = mon < 1 ? 1 : mon > 12 ? 12 : mon;
cal.set(Calendar.MONTH, mon-1);
year = (year<1900)?1900:(year>2100)?2100:year;
cal.set(Calendar.YEAR, year);
// ^ first set year for the line below to work correctly
//with leap years - otherwise, date e.g. 29/02/2012
//would be automatically corrected to 28/02/2012
day = (day > cal.getActualMaximum(Calendar.DATE))? cal.getActualMaximum(Calendar.DATE):day;
clean = String.format("%02d%02d%02d",day, mon, year);
}
clean = String.format("%s/%s/%s", clean.substring(0, 2),
clean.substring(2, 4),
clean.substring(4, 8));
sel = sel < 0 ? 0 : sel;
current = clean;
date.setText(current);
date.setSelection(sel < current.length() ? sel : current.length());
}
}
我们还实现了其他两个函数,因为我们必须
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void afterTextChanged(Editable s) {}
};
这会产生以下效果,删除或插入字符将显示或隐藏dd/mm/yyyy
面具。它应该很容易修改以适应其他格式掩码,因为我试图让代码尽可能简单。