Android TextWatcher三个回调详解,监听EditText的输入

article/2025/10/28 5:26:37

TextWatcher是一个监听字符变化的类。当我们调用EditText的addTextChangedListener(TextWatcher)方法之后,就可以监听EditText的输入了。
在new出一个TextWatcher之后,我们需要实现三个抽象方法:

  • beforeTextChanged
  • onTextChanged
  • afterTextChanged

看下beforeTextChanged的注释:

This method is called to notify you that, within s, the count characters beginning at start are about to be replaced by new text with length after. It is an error to attempt to make changes to s from this callback.

不知道你看懂没有,可能是因为英文水平的问题,我反正是看的很含糊不清。
既然这样,那最好的办法就是自己打个log试一下了。

    EditText et = (EditText) findViewById(R.id.et);TextWatcher watcher = new TextWatcher() {@Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after) {Log.d(TAG, "beforeTextChanged: s = " + s + ", start = " + start +", count = " + count + ", after = " + after);}@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {Log.d(TAG, "onTextChanged: s = " + s + ", start = " + start +", before = " + before + ", count = " + count);}@Overridepublic void afterTextChanged(Editable s) {Log.d(TAG, "afterTextChanged: " + s);}};et.addTextChangedListener(watcher);

首先输入abc123

然后在c和1之间添加一个0,现在文字变成了abc0123,再看下LOGCAT的显示:

再把0给删掉,log如下:

把0替换成12:

通过Log,结合Android源码注释,可以得出结论:

  • beforeTextChanged(CharSequence s, int start, int count, int after)
    s: 修改之前的文字。
    start: 字符串中即将发生修改的位置。
    count: 字符串中即将被修改的文字的长度。如果是新增的话则为0。
    after: 被修改的文字修改之后的长度。如果是删除的话则为0。
  • onTextChanged(CharSequence s, int start, int before, int count)
    s: 改变后的字符串
    start: 有变动的字符串的序号
    before: 被改变的字符串长度,如果是新增则为0。
    count: 添加的字符串长度,如果是删除则为0。
  • afterTextChanged(Editable s)
    s: 修改后的文字

Tips:

**需要特别注意的是,在TextWatcher中setText要小心不要陷入死循环。**即:
文字改变->watcher接收到通知->setText->文字改变->watcher接受到通知->…
在watcher中使用setText的解决方案

关于这三个回调方法调用的时机,可以参考这篇文章

当对EditText使用setText之后,记得再使用setSelection()来设置光标位置。

一个完整的TextWatcher例子:

    // 用于屏蔽空格输入的TextWatcherTextWatcher watcher = new TextWatcher() {private String mBefore;// 用于记录变化前的文字private int mCursor;// 用于记录变化时光标的位置@Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after) {mBefore = s.toString();mCursor = start;Log.d(TAG, "beforeTextChanged: " + s + ", " + mCursor);}@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {Log.d(TAG, "onTextChanged: " + s);}@Overridepublic void afterTextChanged(Editable s) {Log.d(TAG, "afterTextChanged: " + s);// 这里图方便,是在afterTextChanged判断是否输入之后含有空格,并不是最好的方案// 理论上应该在onTextChanged中判断输入内容if (s.toString().contains(" ")) {Log.i(TAG, "onTextChanged: 包含空格, 设置" + mBefore);et.removeTextChangedListener(this);et.setText(mBefore);et.addTextChangedListener(this);et.setSelection(mCursor);}}};et.addTextChangedListener(watcher);

http://chatgpt.dhexx.cn/article/mtybDQsC.shtml

相关文章

android TextWatcher 学习

1.简介 主要用来监听用户输入&#xff0c;然后剪裁输入。 比如输入框只能输入8个字节的内容&#xff0c;就可以用TextWatcher来实现。 public interface TextWatcher extends NoCopySpan {/*** This method is called to notify you that, within <code>s</code>…

android的TextView的TextWatcher使用

TextWatcher是一个文本变化监听接口&#xff0c;定义了三个接口&#xff0c;分别是beforeTextChanged,onTextChanged,afterTextCahnged. TextWatcher通常与TextView结合使用&#xff0c;以便在文本变化的不同时机做响应的处理。TextWatcher中三个回调接口都是使用了InputFilter…

Android 文本监听接口TextWatcher详解

TextWatcher是一个用来监听文本变化的接口&#xff0c;使用该接口可以很方便的对可显示文本控件和可编辑文本控件中的文字进行监听和修改 TextWatcher接口中定义了三个方法&#xff1a; public void beforeTextChanged(CharSequence s, int start, int count, int after) {} 该…

makefile中的两个函数(wildcard和patsubst)

(1) wildcard函数 作用是查找指定目录下指定类型的文件&#xff0c;并最终返回一个环境变量&#xff0c;需要用$取值赋值给另一个环境变量&#xff01;该函数只有一个参数&#xff0c;如取出当前目录下的所有.c文件&#xff0c;并赋值给allc普通变量&#xff1a; allc$(wildc…

linux_makefile文件编写,基本规则、工作原理、模式规则,wildcard函数、patsubst函数

接上一篇&#xff1a;linux_GDB调试学习(调试运行、多文件设置断点)_C/C程序调试 本次来分享linux下的makefile文件的编写&#xff0c;开始上菜&#xff1a; 目录 1.makefile文件的命名规则2.用途3.基本规则3.1.用例一4.工作原理4.1.用例二 5.makefile的执行5.1.用例三 6.make…

makefile wildcard patsubst使用小结

这是当前的目录&#xff1a; objs main.o g_a.o g_b. target : $(objs)gcc -o target $(objs) main.o : g_a.h g_b.hgcc -c main.c g_a.o : g_a.hgcc -c g_a.c g_b.o : g_b.hgcc -c g_b.c.PHONY : cleansrc $(wildcard *.c) obj $(patsubst %.c,%.o,$(src)) #obj $(patsu…

Makefile中patsubst函数使用方法

Makefile中patsubst函数使用方法 patsubst函数用于将文件模式进行替换。 一、作用 替换文件后缀。 二、格式 $(patsubst 原模式&#xff0c; 目标模式&#xff0c; 文件列表) 三、实例 图1 源文件结构 图2 patsubst实例

从零开始学习makefile(5)makefile中patsubst的作用

目录 介绍 text pattern与replacement 返回值 通配符% 示例1 例子2 介绍 patsubst是pattern substitute的缩写。其用法是&#xff1a; $(patsubst pattern,replacement,text) text text是将要被处理的字符串。首先&#xff0c;patsubst以空格为分隔符&#xff0c;将te…

list_for_each_entry和list_for_each_entry_safe

看内核代码都会发现&#xff0c;内核链表的操作常用的二个宏list_for_each_entry和list_for_each_entry_safe 循序渐进&#xff0c;先从最底层的函数container_of函数说起&#xff0c;其内核定义如下&#xff1a; 先看offsetof宏&#xff0c;根据优先级的顺序&#xff0c;最里面…

Map中的entry,entrySet,keySet的区别和用法

Map中的元素是以键值对的形式存在的&#xff0c;即key-value。key是唯一的不能重复&#xff0c;但value可以重复。 Map.keySet(): 这个方法返回的就是map集合中所有键Key的一个Set集合。如Map<Integer&#xff0c;String> 中put(1, “张三”)&#xff0c;put(2, “李四”…

Map.Entry与entrySet与entry,getKey()与entry.getValue()的用法

直接上代码 实体类 Data AllArgsConstructor NoArgsConstructor public class SinglePressureResultDTO {private Integer Times; private Integer SCU_number; private Boolean Intervention; private Long startTime_low; private Long low_time; private Long start…

Map集合的entrySet()方法

之前学习集合的时候要通过迭代器来迭代的时候最难得就是map集合得迭代&#xff0c;一直也不太明白&#xff0c;今天总算搞懂了 首先我们看什么容器才能迭代 根据API我们得知是对所有collection迭代的集合&#xff0c;那么已知的collection容器有哪些 我把常用的标出了&#xf…

keySet()和entrySet()

一、描述 keySet()和entrySet()&#xff0c;是Map集合中的两种取值方法。 与get(Object key)相比&#xff0c;get(Object key)只能返回到指定键所映射的值&#xff0c;不能一次全部取出。而keySet()和entrySet()可以。 Map集合中没有迭代器&#xff0c;Map集合取出键值的原理…

Java高级之HashMap中的entrySet()方法

基本使用 entrySet()方法得到HashMap中各个键值对映射关系的集合。 然后Map.Entry中包含了getKey()和getValue()方法获取键和值。 示例&#xff1a; public class Demo {public static void main(String[] args) {Map<String, String> map new HashMap<>();ma…

KeySet和EntrySet区别

场景&#xff1a; keySet()和entrySet()&#xff0c;是Map集合中的两种取值方法。 与get(Object key)相比&#xff0c;get(Object key)只能返回到指定键所映射的值&#xff0c;不能一次全部取出。而keySet()和entrySet()可以。 Map集合中没有迭代器&#xff0c;Map集合取出键…

Map中entrySet()方法使用

public Set<Map.Entry<K,V>> entrySet(): 获取到Map集合中所有的键值对对象的集合(Set集合)。 就是返回一个集合&#xff0c;集合里存放的是对象&#xff0c;创建对象的类有两个属性&#xff0c;分别是 键和值 也即键值对。 其中Entry是属于Map的静态内部类&#x…

glPushMatrix 和glPopMatrix图解 ----求别笑

猜想&#xff1a; openGL在绘制场景时的一般用法是&#xff1a; 首先在函数的开始处用glLoadIdentity()设置当前的矩阵为单位矩阵。 然后在函数中用glPushMatrix()和glPopMatrix()函数进行操作&#xff1a; 根据实践判断&#xff1a; 即这两者是分开的&#xff0c;并不是当前…

OpenGL的glPushMatrix和glPopMatrix矩阵栈顶操作函数详解

OpenGL中图形绘制后&#xff0c;往往需要一系列的变换来达到用户的目的&#xff0c;而这种变换实现的原理是又通过矩阵进行操作的。opengl中的变换一般包括视图变换、模型变换、投影变换等&#xff0c;在每次变换后&#xff0c;opengl将会呈现一种新的状态&#xff08;这也就是…

为什么调用glPushMatrix()和glPopMatrix()

2019独角兽企业重金招聘Python工程师标准>>> 今天忽然感悟到为什么在进行变换之前要用glPushMatrix();这个函数&#xff0c;而在变换完毕后有用glPopMatrix()这两个函数了,赶紧记下来&#xff1a; 我们在变换坐标的时候&#xff0c;使用的是glTranslatef(),glRotaef…

opengl入门记录--glPushMatrix和glPopMatrix原理

glPushMatrix、glPopMatrix操作事实上就相当于栈里的入栈和出栈。 很多人不明确的可能是入的是什么&#xff0c;出的又是什么。 比如你当前的坐标系原点在你电脑屏幕的左上方。如今你调用glPushMatrix&#xff0c;然后再调用一堆平移、旋转代码等等&#xff0c;然后再绘图。那…