0

我有一個表單,用戶可以在EditText字段中輸入一些數據。其中一個EditText小部件用於電子郵件地址。我使用的是TextWatcher以確保文本始終是小寫如下:Android - EditText TextWatcher保持小寫,不能保留插入符號(輸入光標)的位置

txtEmail.addTextChangedListener(new TextWatcher() 
    { 
     String prevString = ""; 
     boolean delAction = false; 

     @Override 
     public void beforeTextChanged(CharSequence s, int start, int count, int after) 
     { 

     } 

     @Override 
     public void onTextChanged(CharSequence s, int start, int before, int count) 
     { 
      if (s.length() < prevString.length()) 
       delAction = true; 
      else 
       delAction = false; 
     } 

     @Override 
     public void afterTextChanged(Editable s) 
     { 
      if (!delAction) 
      { 
       String temp = s.toString().toLowerCase(); 
       if (!temp.equals(prevString)) 
       { 
        prevString = temp; 
        txtEmail.setText(temp); // Recursive 
        txtEmail.setSelection(temp.length()); 
       } 
      } 
      else 
      { 
       prevString = s.toString(); 
      } 
     } 
    }); 

onTextChanged(...)我也做一個比較,以確保刪除工作正常。

現在來解決問題。 txtEmail.setText(temp);導致整個Watcher遞歸運行。通過添加txtEmail.setSelection(temp.length());並使用if轉義遞歸循環,我可以控制插入位置到EditText的末尾,但我無法找到一種方法將我的插入符號保留在特定位置。例如,如果我寫了「myema(il missing)@ something.com」,並且想要返回來對每個字母進行修改,那麼在字符串結尾處插入脫字符號。

現在是奇怪的部分。在beforeTextChanged(...)onTextChanged(...)之前插入的插入符的位置在我鍵入內容時,插入符的位置在每種情況下都被適當地改變了,但是,當我們輸入遞歸調用時插入符的位置被報告爲0。當我實際鍵入時,插入符號運動也被註冊,但是因爲在遞歸調用中沒有插入符號的移動,而不是在EditText中「粘貼」文本,所以我沒有找到位置變化。我保持脫字符的位置?我曾經是實際將字符串分文本。將所有內容都寫入插入符號中,使其更改將其與txtEmail.setSelection(temp.length());一起扔到那裏,然後在其他步驟中添加字符串的其餘部分(尚未嘗試過)。是否有任何其他(更簡單/更高效)的方式可以通過內置工具處理?

在此先感謝!

+0

你爲什麼把它反正結束了? – creativecreatorormaybenot

回答

1

也許你已經走近了這艱難的路。爲什麼不使用

android:digits="qwertyuiopasdfghjklzxcvbnm_,[email protected]," 

EditText for email?如果您允許用戶輸入任何其他字符,只需將其添加到android:digits字段。

編輯由OP:

以下亞歷山的意見後(見註釋)註銷並重新註冊TextWatcher,代碼改變,工作原理如下:

txtEmail.addTextChangedListener(new TextWatcher() 
    { 
     String prevString = ""; 
     boolean delAction = false; 
     int caretPos = 0; 

     @Override 
     public void beforeTextChanged(CharSequence s, int start, int count, int after) 
     { 
      caretPos = txtEmail.getSelectionStart(); 
     } 

     @Override 
     public void onTextChanged(CharSequence s, int start, int before, int count) 
     { 
      if (s.length() < prevString.length()) 
       delAction = true; 
      else 
       delAction = false; 
     } 

     @Override 
     public void afterTextChanged(Editable s) 
     { 
      if (!delAction) 
      { 
       prevString = s.toString().toLowerCase(); 
       txtEmail.removeTextChangedListener(this); 
       txtEmail.setText(prevString); 
       txtEmail.addTextChangedListener(this); 
       txtEmail.setSelection(caretPos + 1); 
      } 
      else 
      { 
       txtEmail.setSelection(caretPos - 1); 
       prevString = s.toString(); 
      } 
     } 
    }); 
+0

這種方法最大的問題是,如果我輸入大寫字母,則字符根本不會註冊。另外我需要基本上把整個鍵盤放在'android:digits =「...」'中,根據[電子郵件地址的形式定義]覆蓋所有可能的組合(https://en.wikipedia.org/wiki/Email_address#Syntax )。 我搜索了很長時間,很難找到我想要的功能,我認爲這是實現它的唯一方法。我很想被證明是錯誤的,但是;) – MadDim

+0

啊哈,所以如果用戶輸入大寫'A',你必須顯示小寫字母'a'?爲了避免設置光標手動,在使用'txtEmail.setText(temp)'設置文本之前只註銷TextWatcher,然後再註冊它是否有幫助?我猜,這樣你可以優雅地避免遞歸調用。 –

+0

Aaaand你搖滾......從來沒有想過試圖取消註冊TextWatcher。它實際上看起來很奇怪,當我讀到你的評論時,在裏面取消註冊!顯然,Java/Android並不在意(這個''真是神奇有時!)和它的作品!如果您不介意,我將編輯您的答案,並對所做的更改進行標記。 – MadDim

相關問題