sug*_*fle 13 java android phone-number textwatcher android-edittext
我正在尝试使用来自Google的libphonenumber的AsYouTypeFormatter和TextWatcher,我不确定它是否可行.我已经能够将文本格式化为从EditText字段输入并将其输出到另一个EditText但不能直接更改原始的EditText字段(这就是我想要的).我知道phoneNumberFormattingTextWatcher,但我们希望用户能够最终选择他们所在的区域设置,并且比使用允许的区域具有更多的控制权(从我收集的内容).
顶级:
private View phoneNumberView;
private EditText phoneNumberText;
private String formattedPhoneNumber;
private boolean isInAfterTextChanged;
private AsYouTypeFormatter aytf;
Run Code Online (Sandbox Code Playgroud)
首先,我在我的类顶部初始化AsYouTypeFormatter:
aytf = PhoneNumberUtil.getInstance().getAsYouTypeFormatter(Locale.getDefault().getCountry());
Run Code Online (Sandbox Code Playgroud)
在创建了我的标签之后,我创建一个EditText框,格式化其中的现有电话号码(可以工作),并附加监听器(这是当前的类):
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);
Run Code Online (Sandbox Code Playgroud)
那么这就是我目前在TextWatcher函数中所拥有的,我不确定我的代码中应该包含哪些函数:
@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) {
}
Run Code Online (Sandbox Code Playgroud)
以下是记录输出的示例,因此我知道格式化正在运行:
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
Run Code Online (Sandbox Code Playgroud)
这里是输出的图像(顶部EditText是phoneNumberText,底部是testPhoneNumberText):http://imgur.com/GXwRu.png
我想知道的是如何将格式化的输出恢复到原始的EditText中,因为它正在输入?当我尝试这样做时,奇怪的事情发生就像复制一样,或只是显示它没有格式化.我尝试过使用s.replace(),但我不确定我是否正确使用它.这可能吗?谢谢?
对于那些只想在用户输入的EditText中格式化用户输入的电话号码的其他人来说,使用它PhoneNumberFormattingTextWatcher(内置于Android)比尝试任何这些冗长的答案要容易得多 - 而且它是一行代码!
//Add a special listener for this instance that will format phone numbers on the fly.
this.editText.addTextChangedListener(new PhoneNumberFormattingTextWatcher());
Run Code Online (Sandbox Code Playgroud)
你也可以传递用户选择的区域,我认为这实际上会回答OP的问题,但是在API 21之前它是不可用的:
//This version takes a country code!
this.editText.addTextChangedListener(new PhoneNumberFormattingTextWatcher("US"));
Run Code Online (Sandbox Code Playgroud)
我最终在顶部声明了一个新的String:
private String unformattedPhoneNumber;
Run Code Online (Sandbox Code Playgroud)
然后将我的代码更改为此:
@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;
}
Run Code Online (Sandbox Code Playgroud)
}
看来aytf无法格式化已经部分格式化的电话号码,因此我必须在重新提交给aytf之前剔除所有非数字?现在剩下的唯一问题是EditText字段中的光标位于开头而不是结尾,但这不是要解决的问题。好极了。
编辑代码:
@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;
}
Run Code Online (Sandbox Code Playgroud)