美文网首页
想要处理输入内容,别用 TextWatcher 了,试试 Inp

想要处理输入内容,别用 TextWatcher 了,试试 Inp

作者: jkwen | 来源:发表于2021-05-28 08:26 被阅读0次

介绍

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
    }

参考内容

android EditText限制输入框小数位数

相关文章

网友评论

      本文标题:想要处理输入内容,别用 TextWatcher 了,试试 Inp

      本文链接:https://www.haomeiwen.com/subject/cqafsltx.html