欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

InputFilter 拦截过滤删除操作

程序员文章站 2022-05-10 19:56:44
...

Android 成长在于积累和分享

原文地址:https://www.jianshu.com/p/bf1168e46901

前言

InputFilter的使用目的是过滤,那么在某一些特殊情况下,除了要过滤不合理的输入操作,同样也要处理过滤不合理的删除操作,大部分人会下意识的认为使用return “” 即是不做任何操作,但其实对于删除来说,这样并不能将删除的操作过滤掉!

分析

首先,不能盲目看别人的结论,还是要结合源码去分析InputFilter是如何进行过滤的。

Source


package android.text;

/**
 * InputFilters can be attached to {@link Editable}s to constrain the
 * changes that can be made to them.
 */
public interface InputFilter
{
    /**
     * This method is called when the buffer is going to replace the
     * range <code>dstart &hellip; dend</code> of <code>dest</code>
     * with the new text from the range <code>start &hellip; end</code>
     * of <code>source</code>.  Return the CharSequence that you would
     * like to have placed there instead, including an empty string
     * if appropriate, or <code>null</code> 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 <code>dest</code>
     * from this method; you may only examine it for context.
     * 
     * Note: If <var>source</var> is an instance of {@link Spanned} or
     * {@link Spannable}, the span objects in the <var>source</var> should be 
     * copied into the filtered result (i.e. the non-null return value). 
     * {@link TextUtils#copySpansFrom} can be used for convenience.
     */
    public CharSequence filter(CharSequence source, int start, int end,
                               Spanned dest, int dstart, int dend);
}

不必要的代码就不贴了,只看下filter方法的说明即可。其中有一句很关键的信息: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.

说的已经很明白了,return的字符串使用来替换当前的操作的,这个时候如果返回空字符串,则表示使用空字符替换当前的输入,返回 null 则表示认同当前的操作,可以认为是不做任何处理。

一般情况下返回空字符的时候基本就相当于拦截了输入的操作,但是如果是删除的话,返回空字符则同等于使用空字符替换要删除的内容,这样的话就不能达到拦截删除的操作。

解决方式

那么想要使当前删除操作无效的话,该怎么去做呢 ?既然返回的字符串是用来替换当前的操作结果的,那么是否可以将其删除的内容获取到,并返回给父级处理,这样就等于把删除的内容去替换删除的操作。结果相当于什么都没能删除掉,本次删除无效,就可以达到拦截删除的目的了。

public class TestDeleteInputFilter implements InputFilter {

    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        // delete
        if (source.length() == 0 && dend > dstart) {
            // 通过添加已删除的内容达到不删除的效果
            return dest.subSequence(dstart, dend);
        }
        return null;
    }
}

测试效果

例子:字符操作只允许从尾端删除,不可以从中间删除。

public class TestDeleteInputFilter implements InputFilter {

    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        // delete
        if (source.length() == 0 && dend > dstart) {
            if (dend != dest.length()) {
                // 非尾端删除
                // 通过添加已删除的内容达到不删除的效果
                return dest.subSequence(dstart, dend);
            }
        }
        return null;
    }
}

效果展示

InputFilter 拦截过滤删除操作

总结

遇到问题的时候首先要明白其工作机制,多看下源码,也许答案就在源码中已经说明过。