Android的EditText超出字数限制,给用户提示

Android的EditText超出字数限制,给用户提示

导语

如果项目着急使用,直接将下面代码复制到项目中,当做自定义的EditText使用就可以了。
建议将后面的解决思路看一遍,增强自己阅读源码的能力。

自定义的MaxLengthEditText

/**
 * Created by Kevin on 2016/6/12.
 * EditText如果限制了最大输入,超出的话,给出相应的提示
 */
public class MaxLengthEditText extends EditText {

    public MaxLengthEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        initLength(attrs, context);
    }

    public MaxLengthEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initLength(attrs, context);
    }


    private void initLength(AttributeSet a, Context context) {
        //命名空间(别告诉我不熟悉)
        String namespace = "http://schemas.android.com/apk/res/android";
        //获取属性中设置的最大长度
        int maxLength = a.getAttributeIntValue(namespace, "maxLength", -1);
        //如果设置了最大长度,给出相应的处理
        if (maxLength > -1) {
            setFilters(new InputFilter[]{new MyLengthFilter(maxLength,context)});
        }
    }


    /**
     * 从源码中复制出来的
     * 来源:InputFilter.LengthFilter
     *
     *
     * 这里只是添加了一句话:
     *              Toast.makeText(context, "字数不能超过" + mMax, Toast.LENGTH_SHORT).show();
     *
     * This filter will constrain edits not to make the length of the text
     * greater than the specified length.
     */
    class MyLengthFilter implements InputFilter {

        private final int mMax;
        private Context context;

        public MyLengthFilter(int max, Context context) {
            mMax = max;
            this.context = context;
        }

        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) {
                //这里,用来给用户提示
                Toast.makeText(context, "字数不能超过" + mMax, Toast.LENGTH_SHORT).show();
                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);
            }
        }

        /**
         * @return the maximum length enforced by this input filter
         */
        public int getMax() {
            return mMax;
        }
    }
}

解决思路

我们是怎么限制输入长度的?

一般,我们是在xml中限制EditText的输入长度的,代码如下:

<EditText
    android:id="@+id/edit_text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:maxLength="5" />

思考:在EditText的源码中,肯定做了某些操作,使得在字符的长度超过5时,我们没有办法再输入任何内容
所以在EditText中查找“maxLength”,看源码中做了什么操作

在EditText查找maxLength相关的部分

在搜索栏中搜索maxLength,你会得到下面的结果

这里写图片描述

没有结果,那么我们从EditText的父类TextView中取搜索,会搜索到以下部分:

这里写图片描述
这里写图片描述
这里写图片描述

解读代码

第一张图片的代码

//maxlength的默认值为-1
int maxlength = -1;

第二张图片的代码

//如果设置了maxlength的属性,获取设置的值,否则为-1
case com.android.internal.R.styleable.TextView_maxLength:
    maxlength = a.getInt(attr, -1);
    break;

第三张图片的代码

if (maxlength >= 0) {
    //如果设置了maxlength,给TextView设置相应的过滤器:LengthFilter
    //具体的操作,可能就在LengthFilter中
    setFilters(new InputFilter[] { new InputFilter.LengthFilter(maxlength) });
} else {
    //没有设置maxLength,设置一个空的过滤器
    setFilters(NO_FILTERS);
}

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;

      //通过构造方法,将maxlength赋值给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 - x;
          //可以猜想:keep表示当前字符超出maxLength的大小
          int keep = mMax - (dest.length() - (dend - dstart));

          //这里对keep的值分别作了判断:
          //keep<=0:也就是当前输入的字符数量大于或者等于maxLength
          //返回"",当字符数量达到maxLength时,我们不能再输入内容,""符合我们的认知
          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);
          }
      }

      /**
       * @return the maximum length enforced by this input filter
       */
      public int getMax() {
          return mMax;
      }
  }

如何自定义一个EditText

Created with Raphaël 2.1.0开始获取maxLength判断maxLength>-1?给EditText添加自定义的过滤器自定的过滤器只是在源码的基础上做一些小修改,可以复制过来在keep <= 0的判断下添加提示操作结束不做处理yesno

自定义的EditText代码详情已经在上面的注释加了,这里就不在重复了

结语

看到这里,你可能发现,解决思路也不是很复杂,源码好像也就是那样,只是平常不愿意看而已
Android作为一个开放的平台,我们一定要利用好源码这一部分来提高自己

转载请标明出处http://blog.csdn.net/qq_26411333/article/details/51647888

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章