maxLength属性不起作用了?可能是与InputFilter冲突了

我们都知道,在做登录时,通常需要对用户名和密码的长度进行限制。而在做长度限制时最简单的方法就是在EditText(或者TextView)中设置maxLength属性。前段时间做了一个项目,需要做登录功能,在对EditText输入长度限制时就用到了这个属性。后来需求又稍有变动,要求在输入时不接受空格和换行,也很简单,对输入框加上输入过滤就行了,如下:

@Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        if (source.equals(" ") || source.equals("\n"))
            return "";
        else
            return null;
    }

这里是让Activity实现InputFilter接口。然后给EditText绑定上该过滤器:

et.setFilters(new InputFilter[]{this});

做完这些,发现输入过滤是可以了,但长度限制居然不再起作用了。确定maxLength属性还在,猜测可能和刚做的输入过滤有关,于是屏蔽掉输入过滤绑定代码,再试长度限制就有效了,原来是maxLength属性和InputFilter冲突了。这又是为什么呢?我们注意到在过滤的方法中有几个int类型的参数,于是猜测应该和长度有关,根据几个参数字面上的意思应该是和end或者dend有关,但具体使用哪一个呢?我们看下这两个参数的说明吧:

This method is called when the buffer is going to replace the
* range <code>dstart … dend</code> of <code>dest</code>
* with the new text from the range <code>start … end</code>
* of <code>source</code>.

大意是说过滤的方法是用resource中的startend之间的输入替换掉bufferdstartdend之间的内容。什么意思呢?其实就是说我们要的输入结果中的第dstartdend位就是一次输入的第startend位。显然dend就输入结果的长度,所以我们要用这个参数对结果长度进行限制,于是把上面的过滤条件修改为:

if (source.equals(" ") || source.equals("\n")||dend>17)
            return "";

运行,果然限制输入长度为18(0-17)个字符。但好奇心强的我并不满足于此,同样为int类型的参数end是用什么用呢?而且在后来的输入测试中发现上面的限制条件也不是完美的,当我们用从别的地方复制内容粘贴到这个输入框时,会发现如果一次性复制的字符串长度大于18位时,也是可以完全粘贴上去的,甚至在连续输入状态下,字符串长度超过限制时同样是可以输入的(也许这里我表达的不太清楚,通俗的说就是,先打出一长串的字符(超过限制),然后点一下就会都显示到输入框了)。那会不会和没用到的参数end有关呢?接着测试,把过滤条件改为:

if (source.equals(" ") || source.equals("\n")||dend>17||end>3)
            return "";

运行,输入,发现当一次性输入或者复制的内容超过3个字符时,输入都是无效的。现在终于明白了,原来end是限制每次输入长度的,而dend是限制总的输入长度的!(之所以设置输入条件的2个参数的大小差别比较大主要是为了易于区分,如果把它们设置一样大小,那即便有效果也不容易弄清楚是哪个参数起的作用)

现在我们才只是弄清楚了那2个各自的作用,我们的主要疑惑,为什么maxLength属性不起作用了还是没弄清楚,还要接着往下找原因。既然是在布局文件中出现的属性,必然和源码有关,我们去看下EditText的源码,发现它是继承自TextView的,跟着去到TextView的源码,可以看到在构造方法中有关于InputFilter的设定:

if (maxlength >= 0) {
    setFilters(new InputFilter[] { new InputFilter.LengthFilter(maxlength) });
} else {
    setFilters(NO_FILTERS);
}

很容易理解,maxlength就是最大字符串长度,初始值为:

int maxlength = -1;

maxLength属性中正是与之对应。从源码中可以看出,如果我们设置了maxLength属性且为正整数,那就会执行setFilters(new InputFilter[] { newInputFilter.LengthFilter(maxlength) });从字面不难看出就是给它绑定长度过滤,我们来看下LengthFilter的实现:

/**
 * This filter will constrain edits not to make the length of the text
 * greater than the specified length.
 */
public static class LengthFilter implements InputFilter {
    private final int mMax;

    public LengthFilter(int max) {
        mMax = max;
    }

    public CharSequence filter(CharSequence source, int start, int end, Spanned dest,
            int dstart, int dend) {
        int keep = mMax - (dest.length() - (dend - dstart));
        if (keep <= 0) {
            return "";
        } else if (keep >= end - start) {
            return null; // keep original
        } else {
            keep += start;
            if (Character.isHighSurrogate(source.charAt(keep - 1))) {
                --keep;
                if (keep == start) {
                    return "";
                }
            }
            return source.subSequence(start, keep);
        }
    }

不难理解。而且这里也从原理上印证了我们对于过滤方法中的参数dendend区别的理解。

接着,如果我们没有设置了maxLength属性(不可以设置小于0的值),就会执行第二句:
setFilters(NO_FILTERS);
NO_FILTERS是个什么东西呢?看源码:
private static final InputFilter[] NO_FILTERS = new InputFilter[0];
这个的 InputFilter[0] 就是没有限制的长度过滤器。

至此,我们终于明白了,原来maxLength属性也是通过InputFilter来实现的,如果我们在代码里给TextView绑定了新的InputFilter,就会覆盖掉maxLength属性,导致无效。

最后,解决办法当然也很明了,比较简单的方法是我们只实现对空格和换行的过滤,长度过滤用系统的LengthFilter,绑定时如下:
et.setFilters(new InputFilter[]{new LengthFilter(10)});
最后,系统的这个LengthFilter和我们自己写的判断条件“ dend>17||end>3”有什么区别呢?区别就是,按照我们自己加的判断条件,当一次性输入长度大于end时,则整个输入都无效。举例来说就是,每次输入限制为5(end>5),假如已经输入16位,这时我们一次性输入大于5个字符时,则整个本次输入都无效,即一个字符也没输入;假设我们限制总的输入长度为17(dend>17),已经输入了17位,再一次性输入5位字符,则可以输入17+5=22位;而系统的长度过滤器则会把这次输入的5位中的第1个输入,使输入长度正好18位,余下的字符串才被过滤掉。
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: 表单是Web页面中一种常见的交互式元素,它可以让用户输入数据并将其提交到服务器进行处理。表单通常包含多个表单元素,如文本框、下拉框、单选框、复选框、按钮等。 文本框是表单中最常见的元素之一,它允许用户输入文本数据。在文本框中,Size属性指定文本框的宽度,即可见字符的数量,而maxlength属性指定文本框能够输入的最大字符数。如果用户试图输入超过maxlength指定的字符数,文本框将不再接受输入。因此,Size属性影响的是文本框的显示效果,而maxlength属性影响的是文本框的输入限制。 ### 回答2: 表单在页面中起到了收集用户输入数据的作用。它可以包含各种元素,如文本框、复选框、单选按钮、下拉框、提交按钮等,用于接收用户输入的数据,并将这些数据传输到服务器进行处理。 文本框是表单中常见的元素之一,用于用户输入文本信息。而文本框空间属性的Size和maxlength则有不同的作用。Size属性定义了目标文本框的宽度,可以通过指定具体像素值或相对值来设置。它影响的是文本框在页面上的显示宽度,而不是用户可以输入的字符的数量限制Maxlength属性则是限制用户在文本框中输入的字符数量上限。可以通过设置一个整数值来限制用户的输入长度,当用户输入的字符数量超过该限制时,系统会自动截断多余的字符。 总之,表单在页面中起到了收集用户输入数据的作用,可以包含文本框、复选框、单选按钮、下拉框等元素。而文本框空间属性的Size用于定义文本框的显示宽度,maxlength用于限制文本框中可以输入的字符数量上限。 ### 回答3: 表单在页面中起到收集用户信息的作用,通过表单用户可以向服务器发送数据。表单可以包含多种元素,常见的有文本框、单选框、复选框、下拉列表等。 文本框是表单中最常见的元素之一,用于输入文本信息。文本框空间属性的Size指的是文本框的宽度,可以设置为一个固定的值或者一个相对的百分比值。这个属性影响文本框的显示宽度,单位可以是字符个数或者像素。 而maxlength属性指的是文本框中最多可以输入的字符个数。当用户输入的字符数量达到maxlength的值时,将无法再继续输入更多字符。这个属性用于限制用户输入的字符数目,常用于限制用户输入框内容的长度。 Size和maxlength两个属性在作用上有一些差别,Size影响文本框的显示宽度,maxlength限制了用户可以输入的字符数目。Size属性常用于控制文本框的显示效果,而maxlength属性则用于限制输入内容的长度。 总之,表单在页面中起到收集用户信息的作用,可以包含各种元素,而文本框的空间属性Size和maxlength分别控制文本框的显示宽度和限制输入内容的长度

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值