TextWatcher使用

TextWatcher作用爲監測鍵盤輸入並根據輸入內容展示不同顯示效果


接口分析(按回調順序)

  1. 文本改變前
@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 sCharSequence s獲取的數據爲去除空格和回車之後字符串.

應用場景

  1. 各種銀行卡/激活碼/手機號/電話號等等輸入框,可根據輸入的內容進行添加空格,破折號或加號等等,形成格式化.
  2. 對於微博,微信朋友圈等等場景多半對於字符串長度有要求,而直觀的加入字數顯示和剩餘字數可提升用戶體驗.
  3. 特殊場景,比如輸入銀行卡時只能輸入數字,身份證只能輸入數字+X,輸入激活碼時全部大寫等等.
  4. 輸入聯想,輸入補全等等,例如商品搜索過程自動改變listview內容,例如輸入郵箱過程中檢測到@時自動顯示常用後綴等等.
  5. 拋磚引玉,歡迎大家發掘更多應用場景

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()destEMPTY_SPANNED,添加或修改時爲輸入框內的文本內容
int dstart dest選中範圍的起始位置
int dend dest選中範圍的結束位置

textView.setFilters(inputFilters);

設置過濾器,inputFiltersInputFilter 數組.

注意事項

  1. setFilters方法爲替換過程,如果直接添加我們自定義的過濾器會導致原本textview自帶的過濾方法失效,比如設置了maxLength屬性會無效.具體方法如下
    //獲取到原來的InputFilter數組
    textView.getFilters();
    ...  //將獲取到的InputFilter數組元素加入新建的數組中
    //設置新的
    textView.setFilters(inputFilters);
  1. 過濾操作在beforeTextChanged回調方法之前進行
  2. 過濾操作是對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時,不對輸入數據進行任何過濾操作,數據不變


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