0

사용자가 EditText 필드에 일부 데이터를 입력 할 수있는 양식이 있습니다. 이 EditText 위젯 중 하나는 이메일 주소입니다. 나는 다음과 같이 텍스트가 항상 소문자로되어 있는지 확인하기 위해 TextWatcher를 사용하고 다음 onTextChanged(...)에서안드로이드 - 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(); 
      } 
     } 
    }); 

나는 또한 비교를하고 제대로 확인하십시오 삭제 작업을 할 수 있습니다.

문제가 생겼습니다. txtEmail.setText(temp);은 전체 감시자가 재귀 적으로 실행되도록합니다. txtEmail.setSelection(temp.length());을 추가하여 EditText의 끝으로 이동하고 if과 함께 재귀 루프를 이스케이프 처리하는 캐럿 위치를 제어 할 수 있지만 특정 지점에서 캐럿을 유지할 수있는 방법을 찾을 수 없습니다. 예를 들어 "myema (il missing) @ something.com"이라고 쓰고 각 문자를 입력 할 때마다 교정을하려고한다면 캐럿은 문자열의 끝에갑니다.

지금 이상한 부분입니다. beforeTextChanged(...) 또는 onTextChanged(...) 앞에있는 캐럿의 위치 내가 입력 할 때마다 캐럿 위치가 모든 경우에 적절히 변경됩니다. 그러나 재귀 호출을 입력하면 캐럿의 위치가 0으로보고됩니다. 실제로 입력 할 때 캐럿 이동도 등록되지만 재귀 호출에는 EditText에서 텍스트를 "붙여 넣기"하는 것이 아니라 캐럿 이동이 없으므로 위치 변경이 없습니다.

따라서 질문 : 어떻게 할 수 있습니까? 나는 캐럿의 위치를 ​​유지합니까? 실제로 텍스트를 하위 문자열로 묶는 것이 었습니다. 캐럿에 대한 모든 것을 가져 와서 변경 사항을 txtEmail.setSelection(temp.length());으로 던져 버린 다음 나머지 단계를 추가합니다 (아직 시도하지 않았습니다). inbuilt 도구로 처리 할 수있는 다른 (더 간단하고 효율적인) 방법이 있습니까?

미리 감사드립니다.

+0

왜에 배치해야합니까 : OP BY

편집 : 다음과 같이

Alexandru의 조언을 따른 후 (설명 참조)의 등록을 취소하고 다시 TextWatcher를 등록하려면, 코드 변경 및 작동 어쨌든 끝이야? – creativecreatorormaybenot

답변

1

어쩌면 당신은이 어려운 방법에 접근했습니다. 왜 사용하지 않습니까?

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

EditText for email? 사용자가 다른 문자를 입력 할 수있게하려면 android : digits 필드에 추가하십시오.

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 you rock ... 결코 TextWatcher의 등록을 취소하려고하지 않았습니다. 그것은 실제로 이상하게 보였습니다, 당신의 코멘트를 읽을 때, 등록되지 않은 동안! 분명히 자바/안드로이드는 상관하지 않습니다 (''이것은 진정으로 마법입니다!) 그리고 그것은 작동합니다! 상관 없으면 나는 내가 한 변화로 당신의 대답을 편집 할 것이고 나는 그것을 표시 할 것입니다. – MadDim