侧边栏壁纸
博主头像
Z同学博主等级

工作磨平激情前,坚持技术的热忱。 欢迎光临Z同学的技术小站。 分享最新的互联网知识。

  • 累计撰写 274 篇文章
  • 累计创建 55 个标签
  • 累计收到 74 条评论

Android EditText输入监听TextWatcher 的详细介绍

Z同学
2021-12-29 / 0 评论 / 0 点赞 / 945 阅读 / 2,805 字
温馨提示:
本文最后更新于 2022-01-04,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

1.介绍

如果要实时监控EditText的输入情况。根据输入的情况进行其他事务的响应。

那么我们只需要在EditText控件上添加TextWatcher的监听。就可以把握整个EditText 的输入前,输入中,以及输入后的状态。

其他的EditText的扩展的例如:TextInputEditText也是支持TestWatcher的监控的。

2. TextWatcher详解

在使用前,我们先了解TextWatcher这个对象。

TextWatcher 是一个接口类。主要有以下三个方法:

void beforeTextChanged(CharSequence var1, int var2, int var3, int var4);
//文本内容改变前

void onTextChanged(CharSequence var1, int var2, int var3, int var4);
//文本内容改变中

void afterTextChanged(Editable var1);
//文本内容改变后

从方法名上,我们就可以很简单的区分三个接口到底是干嘛了。

关键是它的几个接口传参到底是怎么使用的。

2.1 接口的调动顺序

我们先了解这三个接口是怎么调用的:

zinyenEditText.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        Log.e("TextInputEditText", "beforeTextChanged 修改前:" + charSequence);
    }

    @Override
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        Log.e("TextInputEditText", "onTextChanged 修改中:" + charSequence);
    }

    @Override
    public void afterTextChanged(Editable editable) {
        Log.e("TextInputEditText", "afterTextChanged 修改后:" + editable.toString());
    }
});

然后我们输入不同的情况下。看看它的日志输出结果是如何的。

  1. 光标点击时:TextWatcher事件不会被触发
  2. EditText.setText():TextWatcher事件会被触发。分别从上到下执行,beforeTextChangedonTextChangedafterTextChanged。不管setText() 里面是否有传值,都会触发TextWatcher事件。

下面看看在输入的情况下,会有什么结果:

2.1.1 添加字符

 EditText 输入z
 E/TextInputEditText: beforeTextChanged 修改前:
 E/TextInputEditText: onTextChanged 修改中:z
 E/TextInputEditText: afterTextChanged 修改后:z

效果图如下:

image-20211229154224805

我们如果继续输入,可以看到我们一直往后输入,那么修改中和修改后的结果是一样的。

image-20211229154526034

那么我们如果光标移动到中间会是什么效果呢?我们将光标移动到开头,进行输入得到的效果如下。

image-20211229154844134

2.1.2 删除字符

我们如果删除前面的Yan 会是什么效果呢?

image-20211229155017468

2.1.3 修改字符

例如剪切和粘贴。整个修改添加状态是一样的。只是不会在一个一个字符进行监控而已。

例如剪切

image-20211229155421208

粘贴:

image-20211229155510872

通过上面的例子我们可以看到。EditText输入框中的所有字符的变动情况,我们如果要匹配用户输入的长度,用户当前输入的结果等等,都可以通过这个进行监听获取结果了。

上面的三个接口变动顺序很快,而且永远都是beforeTextChanged->onTextChanged->afterTextChanged这个顺序进行执行的。

2.2 接口各参数介绍

上面的例子介绍了CharSequence 的变动,后面的几个参数的变动我直接写了。就不进行示例打印了。因为大部分情况下,我们也用不上。

public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2)

  • CharSequence charSequence: editText 修改前的字符串
  • int var2: 字符串中要开始发生修改的位置(也就是我们光标的位置)
  • int var3: 字符串中即将被修改的文字的长度(如果光标在最后,那么就是0)
  • int var4: 字符串中被修改的文字长度。如果是删除的话就是0

public void onTextChanged(CharSequence charSequence, int i, int i1, int i2)

  • CharSequence charSequence: 当前修改后的字符串
  • int i: 有变动的字符串的下标值
  • int i1: 被改变的字符串长度,如果是新增长度为0
  • int i2: 添加的字符串长度,如果是删除值为0

public void afterTextChanged(Editable editable)

  • Editable editable: 修改后的字符串。

其实不建议在TextWatcher的函数中,执行EditText字符串的修改。我们只是用它来监听输入指定长度,或者输入匹配正则的结果时,我们执行其他的动作而已。

3.避免死循环

1.我们开头就说了。如果调用setText 方法,就会触发TextWatcher事件。我们如果在beforeTextChanged,onTextChanged,afterTextChanged 这三个方法中,任意地方进行setText修改都会造成死循环一直重复触发TextWatcher

2.我们如果在afterTextChanged 方法中,修改Editable对象,也会进行死循环。

解决方法:

zinyanEdit.removeTextChangedListener(TextWatcher);
zinyanEdit.setText("修改结果");
zinyanEdit.addTextChangedListener(TextWatcher);

我们在必须修改的地方,先执行remove移除TextWatcher监听。然后修改完毕后,再add加入TextWatcher监听。也能规避。

但是这种就不够优雅了。

本质上来说,这个接口只是用来监听输入的内容和长度的,并不太建议在这个方法中进行字符串的替换。

如果要在输入过程中进行字符替换修改。建议使用InputFilter进行监听。

0

评论区