介绍
InputFilter 是个接口,可以通过 InputFilter 接口对编辑框的输入内容做过滤处理,系统提供了两个实现 AllCaps 和 LengthFilter。另外还有一点要注意,考虑到编辑框赋值时是个数组,所以按理来说是可以做多重过滤来完成更复杂的事。
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend);
先说明 Spanned 是 CharSequence 的子类,Spannable 是 Spanned 的子类,这里为了简单理解,都认为是 CharSequence 好了。
各参数说明
source 表示新变动的内容,就是通过赋值或者手动输入后的内容,比如键盘输入一个 a,那么 source 的值就是 a。
start, end 表示新变动的内容的开始和终点坐标,从 0 开始,所以 end - start 就可以认为是新内容的长度。
dest 表示 source 还未生效时的当前内容,例如编辑框原来是空的,此时输入一个 1,那么 dest 就是空值,接着如果输入 2,那么 dest 就是 1。
dstart, dend 表示当前光标的位置,从 0 开始,通常 dstart 和 dend 是相同的,是几就表示在位置几的后面,例如上面说输入了 2,但还没有展示 2 时,dest 是 1,dstart 就是 1,dend 也是 1,光标就在 1 的后面。
以上是以编辑框的输入类型是 numberDecimal 来说的,如果是 textAutoComplete 等以单词形式输入的,情况就不同了。区别在于单词形式的输入会认为这些字母是一起的,有下划线连着,而普通输入都是独立的一个一个。
来看几张图的对比 输入单词时的输入框.jpg输入单词时的 inputFilter.jpg 输入数字时的 inputFilter.jpg
同样的差异还表现在删除操作上,普通的删除,source 都是空值,而单词的删除就不同,
删除单词时的inputFilter.jpg显然对于输入类型的不同,过滤逻辑也会有所差别,好在我目前我只想对金额输入框进行逻辑过滤,暂且就不讨论单词输入的情况。
接口方法的返回值表示我们期望添加到输入框里的新内容,如果不做改动则返回 null,其他则根据情况来定。
最后,以我的需求为例,要求金额输入整数部分没有限制,小数部分最多只能输入两位,
override fun filter(
source: CharSequence?,
start: Int,
end: Int,
dest: Spanned?,
dstart: Int,
dend: Int
): CharSequence? {
//由于接口是 Java 实现,默认返回值是不能为空的,但为了逻辑完整需要变为可空
dest?.let { outIt ->
source?.let {
//当新输入的内容包含 . 时,需要就几个情况讨论下
if (it.contains(".")) {
//此时输入框里没有内容,
//意思就是以 . 开头的输入,我将其转变为 0.
if (outIt.isBlank()) {
return "0."
}
//此时输入框里的内容已经有 . 了
//意思是 . 只能有一个,那么就不要再增加任何内容了
if (outIt.contains(".")) {
return ""
}
//dstart 和 dend 只有在单词书写时才会不同,这里认为值相同
//这种情况表示,手动移动了光标位置,且即将在新的光标位置上插入一个 .
//那么要考虑如果 . 加上后小数位超过两位的情况,
//超过两位那么就不允许增加
if (outIt.length - dstart > 2) {
return ""
}
}
}
//另外当输入框现有内容已经有 . 的情况,如果小数位已经达到两位了
//那么新输入的内容就不能再增加了
//如果要限制整数部分的位数,在这里也好控制的
val pointIndex = outIt.indexOf(".")
if ((pointIndex > 0) && (outIt.length - pointIndex > 2)) {
return ""
}
}
//其他情况不做过滤
return null
}
网友评论