对于移动端开发来讲,这种需求是很常见的,需要对手机号、银行卡号添加空格或者横线便于用户阅读,总体来说还是很简单的一个需求,实现起来说简单也简单,但是没选择正确的方法也是稍微有点麻烦的。为什么这么说呢,前几天浏览博客看到一篇文章实现了输入手机号添加空格,不过只考虑了末尾输入这一种情况,网上搜索了一下,大多数也是没有考虑所有的情况,中间插入、删除,复制等,所以如果用最常规的对输入的字符串输入后进行格式化,那么就需要考虑的是光标的位置,需要一定的耐心调试,本文采用另一种相对简单的方式来实现。
对于 EditText 实现添加空格,实现这个需求肯定是要调用 addTextChangedListener 这个接口,监听输入的变化情况。最开始我是使用对输入后的字符串进行格式化,但是就是针对每种情况设置光标的位置比较麻烦,我也尝试了写出来了,不过就是处理复制任意长的字符串光标不好精确设置。我后面发现通过 Editable 来插入、删除等是不需要考虑光标的, 关于 EditTable 可以参照这篇文章 TextView源码解析 。那么实现就相对简单很多,话不多说看代码:
private static final char space = ' '; //也可以是'-'
private MyTextWatch myTextWatch;
myTextWatch = new MyTextWatch();
editText.addTextChangedListener(myTextWatch);
private class MyTextWatch implements TextWatcher {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
format(s);
}
}
private void format(Editable s) {
if (s.length() < 4) return;
editText.removeTextChangedListener(myTextWatch);
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == space) {
s.delete(i, i + 1);
}
}
int length = s.length();
if (length > 7) {
s.insert(3, String.valueOf(space));
if (editText.getSelectionStart() == 4) {
editText.setSelection(3);
}
s.insert(8, String.valueOf(space));
if (editText.getSelectionStart() == 9) {
editText.setSelection(8);
}
} else if (length > 3) {
s.insert(3, String.valueOf(space));
if (editText.getSelectionStart() == 4) {
editText.setSelection(3);
}
}
editText.addTextChangedListener(myTextWatch);
}
然后为了防止 Editable 的删除 、插入操作调用监听进入死循环,我们可以先移除监听,然后完成相关操作后果再添加。上述做法也是先对输入的字符串进行去除空格进行111 1111 1111这种格式进行格式化,不过这种还是需要处理光标的问题,因为你刚好中间输入或者删除,后面一位是空格并且字符串去掉空格长度过后大于3的话,光标插入就自动在空格后面而不在字符串后面,删除呢就不能删除中间的空格,删除了一位空格又马上插入了一个空格,显然是不对的。
所以我们上述代码做了如下处理:
if (editText.getSelectionStart() == 4) {
editText.setSelection(3);
}
if (editText.getSelectionStart() == 9) {
editText.setSelection(8);
}
只要光标在空格后面就自动移到字符串的后面,就像下面这种:
当然也可以不自动移动,只需要判断是删除的时候不添加这段代码即可,什么时候是删除的时候呢,就是 onTextChanged(CharSequence s, int start, int before, int count) 中 count 等于0的时候。
实现银行卡呢,那就更简单了,只需要对每一个四位添加空格,乃至推广到间隔几个数字的空格,代码如下:
private static final int divide = 4;
if (length > 0 && length / divide > 0) {
for (int i = 0; i < length / divide; i++) {
s.insert((i + 1) * divide + i, String.valueOf(space));
if (editText.getSelectionStart() == (i + 1) * divide + 1 + i) {
editText.setSelection((i + 1) * divide + i);
}
}
}
代码思路跟上面是一样的,没有什么好解释的了,遇到间隔5个、6个,重新设置一下参数就好了,所以最终成果是这样的:
这篇文章越写感觉这个需求不难,但是我还是记录一下吧,有问题的或者有更好的方法欢迎大家吐槽,哈哈。最近感觉博客有的页面广告等干扰越来越多了,太影响阅读了,给大家推荐一款我发现的 Chrome 插件,简阅,专注阅读,地址在此 简阅。