InputFilter 拦截过滤删除操作

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;
    }
}

效果展示

TestDelete.gif

总结

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值