TextWatcher作用爲監測鍵盤輸入並根據輸入內容展示不同顯示效果
接口分析(按回調順序)
- 文本改變前
@Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {}
其中有4個參數:
* CharSequence s
:文本改變之前的內容
* int start
: 被替換文本區域起點位置
* int count
:將被替換的文本區域字符數目
* int after
:替換後的文本字符數目
文本 s 中的 start 位置之後的 count 個字符將被替換爲 after 個新的字符
注:s爲替換前的文本
2. 文本改變時
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
其中有4個參數:
CharSequence s
:文本改變之後的內容
int start
: 被替換文本區域起點位置,setText時是替換所有內容,此時數值爲0
int before
:被替換之前的文本區域字符數目
int count
:替換後的文本字符數目
文本 s 中的 start 位置之後的 before 個字符已經被替換爲 count 個新的字符
注:s爲替換後的新文本
3. 文本改變後
@Override
public void afterTextChanged(Editable s) {}
其中有1個參數:
Editable s
:文本改變之後的內容
TextWatcher使用
//所有繼承自TextView的類
textView.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void afterTextChanged(Editable s) {}
});
注意事項 :
在回調方法中獲取的新字符串雖然已經設置到
TextView
中,但是還未在UI界面中更新.重要 :
經網上查閱,幾乎沒有人提到過回調方法過程中UI是否已經更新數據,而筆者比較在意是否處理數據導致頁面閃爍.
發現有人已經注意到這一點,其情景爲短時間內多次觸發回調,但是頁面只顯示了最後一次數據結果,而評論中卻歸結爲處理速度快導致分辨不出閃爍.
筆者在回調方法中加入延時,而UI更新時間爲3個回調方法結束後.判斷爲只有在數據處理完畢後纔會顯示在UI上.
如若判斷失誤歡迎大家指正有2種情況會觸發TextWatcher的3個回調方法,
setText()
和EditText
鍵盤輸入- 如果在回調方法中調用
setText()
,會進入無限循環,需要增加判斷條件 afterTextChanged
中去改變Editable s
的值會觸發TextWatcher的3個回調方法,會進入無限循環,需要增加判斷條件Editable s
和CharSequence s
獲取的數據爲去除空格和回車之後字符串.
應用場景
- 各種銀行卡/激活碼/手機號/電話號等等輸入框,可根據輸入的內容進行添加空格,破折號或加號等等,形成格式化.
- 對於微博,微信朋友圈等等場景多半對於字符串長度有要求,而直觀的加入字數顯示和剩餘字數可提升用戶體驗.
- 特殊場景,比如輸入銀行卡時只能輸入數字,身份證只能輸入數字+X,輸入激活碼時全部大寫等等.
- 輸入聯想,輸入補全等等,例如商品搜索過程自動改變listview內容,例如輸入郵箱過程中檢測到@時自動顯示常用後綴等等.
- 拋磚引玉,歡迎大家發掘更多應用場景
InputFilter過濾
InputFilter是系統提供的一個接口,是一個過濾器,修改傳入的字符串,返回值類型爲CharSequence.
自定義InputFilter
public class mInputFilter implements InputFilter {
@Override
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend) {
return null;
}
}
可以看到只需要實現filter()
方法,而方法會傳入6個參數,下面詳細解釋每個參數的含義
CharSequence source
用來替換的新的字符串,包括鍵盤輸入/setText()
/粘貼的內容
int start
source的起始位置
int end
source的結束位置
以上3個參數描述出用來替換的新的字符串
Spanned dest
修改前的字符串,setText()
時dest
爲EMPTY_SPANNED
,添加或修改時爲輸入框內的文本內容
int dstart
dest選中範圍的起始位置
int dend
dest選中範圍的結束位置
textView.setFilters(inputFilters);
設置過濾器,inputFilters
爲InputFilter
數組.
注意事項
setFilters
方法爲替換過程,如果直接添加我們自定義的過濾器會導致原本textview自帶的過濾方法失效,比如設置了maxLength
屬性會無效.具體方法如下
//獲取到原來的InputFilter數組
textView.getFilters();
... //將獲取到的InputFilter數組元素加入新建的數組中
//設置新的
textView.setFilters(inputFilters);
- 過濾操作在
beforeTextChanged
回調方法之前進行 - 過濾操作是對InputFilter數組的元素進行遍歷,需要考慮元素順序對過濾的影響
int n = mFilters.length;
for (int i = 0; i < n; i++) {
CharSequence out = mFilters[i].filter(text, 0, text.length(),
EMPTY_SPANNED, 0, 0);
if (out != null) {
text = out;
}
}
根據源碼得知,當返回值爲null時,不對輸入數據進行任何過濾操作,數據不變