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
自定義的EditText代碼詳情已經在上面的註釋加了,這裏就不在重複了
結語
看到這裏,你可能發現,解決思路也不是很複雜,源碼好像也就是那樣,只是平常不願意看而已。
Android作爲一個開放的平臺,我們一定要利用好源碼這一部分來提高自己轉載請標明出處http://blog.csdn.net/qq_26411333/article/details/51647888