How do I use AsYouTypeFormatter TextWatcher in Android App?
I ended up declaring a new String at the top:
private String unformattedPhoneNumber;
Then changing my code to this:
@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;
}
}
It seems that the aytf wasn't able to format already partially formatted phone numbers so I had to strip out all non digits before resubmitting to aytf? The only problem left now is that the cursor in the EditText field is at the beginning instead of the end now, but that shouldn't be a problem to fix. Yay.
EDITED CODE:
@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;
}
For others out there who just want to format a user-entered phone number in an EditText as the user types, it's much, much easier to use PhoneNumberFormattingTextWatcher
(built in to Android) than attempt any of these verbose answers - and it's ONE LINE OF CODE!
//Add a special listener for this instance that will format phone numbers on the fly.
this.editText.addTextChangedListener(new PhoneNumberFormattingTextWatcher());
You can also pass the region the user has selected, which I think would actually answer the OP's question, but it wasn't available until API 21:
//This version takes a country code!
this.editText.addTextChangedListener(new PhoneNumberFormattingTextWatcher("US"));