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

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