Jua*_*tés 48 android mask textwatcher android-edittext
我如何格式化EditText以遵循" dd/mm/yyyy"格式,就像我们可以使用a TextWatcher来屏蔽用户输入看起来像"0.05€"一样.我不是在谈论限制字符,或者验证日期,只是掩盖了以前的格式.
Jua*_*tés 103
我TextWatcher为一个项目写了这个,希望它对某人有帮助.需要注意的是它并没有验证用户输入的日期,你应该处理时的焦点变化,因为用户可能无法完成输入的日期.
更新25/06制作一个wiki,看看我们是否达到了更好的最终代码.
更新07/06 我终于为观察者本身添加了某种验证.它将执行以下无效日期:
1900-2100,请将其更改为范围这个验证符合我的需要,但你们中的一些人可能想稍微改变一下,范围很容易改变,你可以将这种验证挂钩到Toast例如消息,以通知用户我们已经修改了他/她的日期,因为它是无效.
在这段代码中,我会假设,我们对我们的参考EditText称为date已此TextWatcher连接到它,这是可以做到这样的事:
EditText date;
date = (EditText)findViewById(R.id.whichdate);
date.addTextChangedListener(tw);
Run Code Online (Sandbox Code Playgroud)
TextWatcher tw = new TextWatcher() {
private String current = "";
private String ddmmyyyy = "DDMMYYYY";
private Calendar cal = Calendar.getInstance();
Run Code Online (Sandbox Code Playgroud)
当用户更改文本时 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());
}
}
Run Code Online (Sandbox Code Playgroud)
我们还实现了其他两个功能,因为我们必须这样做
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void afterTextChanged(Editable s) {}
};
Run Code Online (Sandbox Code Playgroud)
这会产生以下效果,删除或插入字符将显示或隐藏dd/mm/yyyy蒙版.应该很容易修改以适应其他格式的掩码,因为我试图让代码尽可能简单.

目前的答案非常好,并帮助指导我自己的解决方案.我决定发布自己的解决方案有几个原因,即使这个问题已经有一个有效的答案:
要使用它,只需执行以下操作:
解决方案如下所示:
class DateInputMask(val input : EditText) {
fun listen() {
input.addTextChangedListener(mDateEntryWatcher)
}
private val mDateEntryWatcher = object : TextWatcher {
var edited = false
val dividerCharacter = "/"
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
if (edited) {
edited = false
return
}
var working = getEditText()
working = manageDateDivider(working, 2, start, before)
working = manageDateDivider(working, 5, start, before)
edited = true
input.setText(working)
input.setSelection(input.text.length)
}
private fun manageDateDivider(working: String, position : Int, start: Int, before: Int) : String{
if (working.length == position) {
return if (before <= position && start < position)
working + dividerCharacter
else
working.dropLast(1)
}
return working
}
private fun getEditText() : String {
return if (input.text.length >= 10)
input.text.toString().substring(0,10)
else
input.text.toString()
}
override fun afterTextChanged(s: Editable) {}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
}
}
Run Code Online (Sandbox Code Playgroud)
使用JuanCortés代码的更简洁方法是将其放在一个类中:
public class DateInputMask implements TextWatcher {
private String current = "";
private String ddmmyyyy = "DDMMYYYY";
private Calendar cal = Calendar.getInstance();
private EditText input;
public DateInputMask(EditText input) {
this.input = input;
this.input.addTextChangedListener(this);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.toString().equals(current)) {
return;
}
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;
input.setText(current);
input.setSelection(sel < current.length() ? sel : current.length());
}
@Override
public void afterTextChanged(Editable s) {
}
}
Run Code Online (Sandbox Code Playgroud)
那你就可以重用
new DateInputMask(myEditTextInstance);
Run Code Online (Sandbox Code Playgroud)
小智 6
尝试使用解决此问题的库,因为屏蔽它不能开箱即用。有很多极端情况(比如在已经屏蔽的文本中间添加/删除字符),要正确处理这个问题,您最终会得到很多代码(和错误)。
以下是一些可用的库:
https://github.com/egslava/edittext-mask
https://github.com/dimitar-zabaznoski/MaskedEditText
https://github.com/pinball83/Masked-Edittext
https://github .com/RedMadRobot/input-mask-android
https://github.com/santalu/mask-edittext
** 请注意,在编写这些库时并非没有问题,因此您有责任选择最适合您的库并测试代码。
| 归档时间: |
|
| 查看次数: |
59968 次 |
| 最近记录: |