在設定Android App的時候,常常會需要讓使用者輸入一些文字,但又不想要讓使用者輸入太多文字,要怎麼樣才可以讓文字輸入框能夠限制使用者輸入的長度呢?如果使用者輸入的文字不是只有半形字,而是還有全形字的話,又該怎麼去計算文字長度呢?
以EditText這個View為例,如果要限制EditText輸入文字的最大長度,可以設定它的「maxLength」屬性。在XML下,可以替EditText加入這個屬性,並指定最大的文字長度。如下面的XML語法,將EditText的可輸入的最大字元數量限制在10個:
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLength="10" />
如果要用Android SDK的Java程式來寫,會比較麻煩一點,可以寫成這樣:
editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(10)});
用以上的方式雖然可以快速地限制EditText的文字長度,但是卻會發生半形字和全形字雖然數量一樣,長度看起來卻差很多的問題。如下圖:
此時可以使用以下的解決方案。
MagicTextLengthWatcher
import android.text.Editable;
import android.text.TextWatcher;
/**
* 限制文字輸入的長度
*
* @author magiclen
*
*/
public class MagicTextLengthWatcher implements TextWatcher {
private int maxLength; // 儲存最大的字串長度
private int currentEnd = 0; // 儲存目前字串改變的結束位置,例如:abcdefg變成abcd1234efg,變化的結束位置就在索引8
public MagicTextLengthWatcher(final int maxLength) {
setMaxLength(maxLength);
}
public final void setMaxLength(final int maxLength) {
if (maxLength >= 0) {
this.maxLength = maxLength;
} else {
this.maxLength = 0;
}
}
public int getMaxLength() {
return this.maxLength;
}
@Override
public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
}
@Override
public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
currentEnd = start + count; // 取得變化的結束位置
}
@Override
public void afterTextChanged(final Editable s) {
while (calculateLength(s) > maxLength) { // 若變化後的長度超過最大長度
// 刪除最後變化的字元
currentEnd--;
s.delete(currentEnd, currentEnd + 1);
}
}
/**
* 計算字串的長度
*
* @param c 傳入字串
*
* @return 傳回字串長度
*/
protected int calculateLength(final CharSequence c) {
int len = 0;
final int l = c.length();
for (int i = 0; i < l; i++) {
final char tmp = c.charAt(i);
if (tmp >= 0x20 && tmp <= 0x7E) {
// 字元值 32~126 是 ASCII 半形字元的範圍
len++;
} else {
// 非半形字元
len += 2;
}
}
return len;
}
}
使用MagicTextLengthWatcher這個TextWatcher,可以很輕易地限制EditText的文字長度。預設將一個半形字元的長度用1計算,一個全形字元的長度用2計算(一個全形字的長度等於兩個半形字的意思)。使用方式如下:
editText.addTextChangedListener(new MagicTextLengthWatcher(10));