Android InputFilter的详细解析

InputFilter这个interface相信大家也不会陌生,任何对EditText的输入第一步就会经过它,而它的名字也十分的直白——输入过滤器.InputFilter只有一个方法,就是filter方法,而这个方法却对你的输入过滤有着至关重要的结果,我们现在看看google的官方文档是怎么描述这个filter方法的.

This method is called when the buffer is going to replace the range dstart … dend of dest with the new text from the range start … end of source. Return the CharSequence that you would like to have placed there instead, including an empty string if appropriate, or null to accept the original replacement. Be careful to not to reject 0-length replacements, as this is what happens when you delete text. Also beware that you should not attempt to make any changes to dest from this method; you may only examine it for context. Note: If source is an instance of Spanned or Spannable, the span objects in the source should be copied into the filtered result (i.e. the non-null return value). [copySpansFrom(Spanned, int, int, Class, Spannable, int)](https://developer.android.com/reference/android/text/TextUtils.html#copySpansFrom(android.text.Spanned, int, int, java.lang.Class, android.text.Spannable, int)) can be used for convenience.

简单翻译:当来自source的新内容(start--end)将要替换之前的内容(dstart--dend)时该方法被调用,返回一串字符串,使用source的内容替代,包括空字符串和null都可以替换原始的位置.需要注意的是当文本被删除时,我们可能会使用0-length的替换。另外还要注意的是,你不应该在这个方法里对原始内容做任何改动,你只是需要检查它的上下文。当缓冲区要用源的范围start ... end中的新文本替换dest的范围dstart ... dend时,将调用此方法。 返回您希望放置的CharSequence,包括空字符串(如果适用),或null以接受原始替换。 小心不要拒绝0长度替换,因为删除文本时会发生这种情况。 还要注意,您不应该尝试对此方法的dest进行任何更改; 你可能只会检查它的上下文。 注意:如果source是Spanned或Spannable的实例,则应将源中的span对象复制到筛选结果中(即非null返回值)。 在copySpansFrom(Spanned,int,int,Class,Spannable,int)中进行处理。

在使用InputFilter时,一般情况下都时在用过键盘输入时,需要过滤的内容,这是输入source一般输入的类型为Spanned的,而且里面会有UnderlineSpan.class的类型的Span在source里,所以这是显示在EditText上的内容是带下划线的,也让用户明白现在是待输入状态.

当在输入框中输入apple时,我们看到log如下的输出,发现source是和上面说的一致的,它并不是普通的CharSequence,而是spanned. ``` I/System.out: source is spanned:true src:a|dest:|dest is spanned:true I/System.out: source is spanned:true src:ap|dest:a|dest is spanned:true I/System.out: source is spanned:true src:app|dest:ap|dest is spanned:true I/System.out: source is spanned:true src:appl|dest:app|dest is spanned:true I/System.out: source is spanned:true src:apple|dest:appl|dest is spanned:true ```

当我继续在输入法中选取Apple这个单词时,log有如下输出:

I/System.out: source is spanned:false src:|dest:apple|dest is spanned:true
I/System.out: source is spanned:false src:Apple|dest:|dest is spanned:true
I/System.out: source is spanned:true src:|dest:Apple|dest is spanned:true

这三个log输出应该都时由输入法触发的,所以如果你需要过滤用户的输入情况,那么一定要考虑到用户输入或者粘贴的内容是否是带有spann样式的.

如果只是需要去除粘贴板中spann的样式.只需:

onTextContextMenuItem(ID_PASTE_AS_PLAIN_TEXT)

即可