2013-01-03 13 views
8

Próbuję użyć AsYouTypeFormatter z libphonanumber Google z TextWatcher i nie jestem pewien, czy jest to możliwe. Byłem w stanie sformatować tekst jako wpisany z pola EditText i wyprowadzić go w innym EditText, ale nie mogłem bezpośrednio zmienić oryginalnego pola EditText (czego chcę). Wiem o telefonieNumberFormattingTextWatcher, ale chcemy, aby użytkownik mógł ostatecznie wybrać, które locale są w nim i mieć większą kontrolę niż używanie tego, co pozwala (z tego, co zebrałem).Jak korzystać z AsYouTypeFormatter TextWatcher w aplikacji na Androida?

Top klasy:

private View phoneNumberView; 
private EditText phoneNumberText; 
private String formattedPhoneNumber; 
private boolean isInAfterTextChanged; 
private AsYouTypeFormatter aytf; 

Najpierw zainicjować AsYouTypeFormatter na szczycie mojej klasy:

aytf = PhoneNumberUtil.getInstance().getAsYouTypeFormatter(Locale.getDefault().getCountry()); 

Po moich zakładkach i takie są tworzone, utworzyć pole EditText, formatowania istniejący numer telefonu wewnątrz (który działa) i dołącz odbiornik (który jest aktualną klasą):

phoneNumberView = inflater.inflate(R.layout.phone_number_setting, null); 
phoneNumberText = (EditText) phoneNumberView.findViewById(R.id.dirty_phone_number); 
phoneNumberText.setText(dirtyPhoneNumber); 
for (int i = 0; i < dirtyPhoneNumber.length(); i++){ 
    phoneNumberText.setText(aytf.inputDigit(dirtyPhoneNumber.charAt(i))); 
} 
aytf.clear(); 
phoneNumberText.setText(dirtyPhoneNumber); 
phoneNumberText.addTextChangedListener(this); 

Wtedy to, co mam w tej chwili w mojej funkcji TextWatcher, nie jestem pewien, które z tych funkcji mój kod powinien być w choć:

@Override 
public void afterTextChanged(Editable s) { 
    if (!isInAfterTextChanged) { 
      isInAfterTextChanged = true; 

      if(s.length() > 0){ 
       Log.v("AsYouTypeFormatter - source", s.toString()); 
       for(int i = 0; i < s.length(); i++){ 
        formattedPhoneNumber = aytf.inputDigit(s.charAt(i)); 
        Log.v("AsYouTypeFormatter - formatted", formattedPhoneNumber); 

       } 
       Log.v("AsYouTypeFormatter - source after loop", s.toString()); 
      //The formatted output shows properly in this EditText but not when I try to put it back into the original one (phoneNumberText) 
       EditText testPhoneNumberText = (EditText) phoneNumberView.findViewById(R.id.testPhoneNumberText); 
       testPhoneNumberText.setText(formattedPhoneNumber); 
       aytf.clear(); 
      } 

      formattedPhoneNumber = null; 
      isInAfterTextChanged = 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) { 
} 

Oto próbka zalogowanych wyjścia, więc wiem formatowanie działa:

01-03 10:55:02.838: V/AsYouTypeFormatter - source(27114): 15552451234 
01-03 10:55:02.838: V/AsYouTypeFormatter - formatted(27114): 1 
01-03 10:55:02.838: V/AsYouTypeFormatter - formatted(27114): 15 
01-03 10:55:02.838: V/AsYouTypeFormatter - formatted(27114): 1 55 
01-03 10:55:02.838: V/AsYouTypeFormatter - formatted(27114): 1 555 
01-03 10:55:02.838: V/AsYouTypeFormatter - formatted(27114): 1 555-2 
01-03 10:55:02.838: V/AsYouTypeFormatter - formatted(27114): 1 555-24 
01-03 10:55:02.850: V/AsYouTypeFormatter - formatted(27114): 1 555-245 
01-03 10:55:02.850: V/AsYouTypeFormatter - formatted(27114): 1 555-245-1 
01-03 10:55:02.850: V/AsYouTypeFormatter - formatted(27114): 1 555-245-12 
01-03 10:55:02.850: V/AsYouTypeFormatter - formatted(27114): 1 555-245-123 
01-03 10:55:02.850: V/AsYouTypeFormatter - formatted(27114): 1 555-245-1234 
01-03 10:55:02.850: V/AsYouTypeFormatter - source after loop(27114): 15552451234 

a oto obraz na wyjściu (top EditText jest phoneNumberText a dno jest testPhoneNumberText): http://imgur.com/GXwRu.png

Co chcę wiedzieć, w jaki sposób mogę uzyskać sformatowany wyjście z powrotem do źródła al EditText podczas pisania? Kiedy próbuję to zrobić, dziwne rzeczy dzieją się jak duplikowanie lub po prostu pokazuje to niesformatowane. Próbowałem używać s.replace(), ale nie jestem pewien, czy używam go poprawnie. czy to możliwe? Dzięki?

+1

Dlaczego nie wystarczy użyć PhoneNumberFormattingTextWatcher (String countryCode) ??? http://stackoverflow.com/a/29109236/1103584 – DiscDev

+0

To wymaga minSdkVersion 21 –

Odpowiedz

3

skończyło się deklarując nowy napis na górze:

private String unformattedPhoneNumber; 

następnie zmieniając mój kod do tego:

@Override 
public void afterTextChanged(Editable s) { 
if (!isInAfterTextChanged) { 
     isInAfterTextChanged = true; 

     if(s.length() > 0){ 
      Log.v("AsYouTypeFormatter - source", s.toString()); 
      unformattedPhoneNumber = s.toString().replaceAll("[^\\d.]", ""); 
      for(int i = 0; i < unformattedPhoneNumber.length(); i++){ 
       formattedPhoneNumber = aytf.inputDigit(unformattedPhoneNumber.charAt(i)); 
       Log.v("AsYouTypeFormatter - formatted", formattedPhoneNumber); 

      } 
      Log.v("AsYouTypeFormatter - source after loop", s.toString()); 

      phoneNumberText.setText(formattedPhoneNumber); 

      aytf.clear(); 
     } 

     formattedPhoneNumber = null; 
     isInAfterTextChanged = false; 
    }   

}

Wydaje się, że nie był w stanie aytf sformatować już częściowo sformatowane numery telefonów, więc musiałem usunąć wszystkie niedodące cyfry przed ponownym przesłaniem do aytf? Jedynym problemem, który pozostało, jest to, że kursor w polu EditText znajduje się na początku zamiast na końcu, ale nie powinno to stanowić problemu. Yay.

EDITED KOD:

@Override 
public void afterTextChanged(Editable s) { 
    if (!isInAfterTextChanged) { 
     isInAfterTextChanged = true; 
     phoneNumberText.setText(pnu.updateNationalNumber(s.toString())); 
     phoneNumberText.setSelection(this.phoneNumberText.getText().length()); 
     isInAfterTextChanged = false; 
    } 
} 

/** 
* Updates the national number based on the param s 
* Takes all formatting out of param s and then reformats the number 
* using the AsYouTypeFormatter for libphonenumber and based upon 
* the region code 
* 
* @param s The formatted value to be used to update the national number 
* @return String The new formatted national number 
*/ 
public String updateNationalNumber(String s){ 
    //Instantiate the as you type formatter with the current region (US or UK) 
    aytf = phoneUtil.getAsYouTypeFormatter(this.currentRegionCode.getCountryCode()); 
    String fNationalNumber = null; 

    //Format the string 
    if(s.length() > 0){ 
     String digitString = null; 
     //If it's in the US remove all leading 1s (international code) 
     if(this.currentRegionCode == RegionCode.US){ 
      digitString = new String(s.replaceAll("(^[1?])|([^\\d.])", "")); 
     } 
     //If it's in the UK remove all leading 44s (international code) 
     else if (this.currentRegionCode == RegionCode.GB){ 
      digitString = new String(s.replaceAll("(^[4?]{2})|([^\\d.])", "")); 
     } 
     if(digitString != null){ 
      //RE input all of the digits into the formatter 
      for(int i = 0; i < digitString.length(); i++){ 
       fNationalNumber = aytf.inputDigit(digitString.charAt(i)); 
      } 
     } 

     //Clear the formatter for the next round of input 
     aytf.clear(); 

     //Try to update the phone number with the formatted number 
     try { 
      phoneUtil.parse(fNationalNumber, this.currentRegionCode.getCountryCode(), this.uPhoneNumber); 
     //Rejects if the number isn't in an acceptable format for the region code given etc. 
     } catch (NumberParseException e) { 
      System.err.println("NumberParseException was thrown: " + e.toString()); 
     } 
    } 
    //Return the formatted phone number 
    return fNationalNumber; 
} 
+0

Nie mogę dodać specjalnego znaku chara, takiego jak +, (,) itd ... co robić? –

+0

Nie powinieneś dodawać +, (,) z tym formaterem, powinien go dodawać za ciebie. Czy możesz wyjaśnić, co próbujesz zrobić? – sugarwaffle

+0

Załóżmy, że użytkownik próbuje wprowadzić liczby z zamierzonymi znakami, myślę, że powinien je zaakceptować :) –

4

Dla innych, którzy tam po prostu chcą, aby sformatować numer telefonu wprowadzone przez użytkownika w EditText jako typów użytkowników, jest to o wiele łatwiejsze w użyciu PhoneNumberFormattingTextWatcher (wbudowane w Androidzie) niż próba jakiejkolwiek z tych gadatliwych odpowiedzi - i to JEDNA LINIA KODU!

//Add a special listener for this instance that will format phone numbers on the fly. 
this.editText.addTextChangedListener(new PhoneNumberFormattingTextWatcher()); 

Można także przekazać region użytkownik wybrał, co moim zdaniem byłoby rzeczywiście odpowiedzieć na pytanie PO, ale to nie był dostępny aż API 21:

//This version takes a country code! 
this.editText.addTextChangedListener(new PhoneNumberFormattingTextWatcher("US")); 
+0

To wymaga zadeklarowania minSdkVersion 21, co prawdopodobnie nie jest możliwe w przypadku większości projektów w tej chwili. –

+2

@LouisMorda tylko przekazywanie wymaganego regionu minSdkVersion z 21 - możesz śledzić region w inny sposób (tak jak robię to w moim projekcie) w celu wsparcia niższa minSdkVersion, właśnie wskazywałem, że jest dostępna. – DiscDev

+1

Na kilka innych wpisów SOF i moje osobiste doświadczenia, działa to tylko na ograniczonej liczbie urządzeń. Dlaczego, nie wiem. – Nick

Powiązane problemy