美文网首页
想要处理输入内容,别用 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