如何在Android应用程序中使用AsYouTypeFormatter TextWatcher?

我正在尝试使用Google的libphonenumber中的AsYouTypeFormatter和TextWatcher,我不确定是否有可能。 我已经能够格式化从EditText字段input文本,并在另一个EditText输出,但不能直接更改原始EditText字段(这是我想要的)。 我知道phoneNumberFormattingTextWatcher,但是我们希望用户能够最终select它们所在的区域,并且比使用允许的更多的控制(从我所收集的)。

上课:

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

首先我在我的类的顶部初始化AsYouTypeFormatter:

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

在创build了我的选项卡之后,我创build一个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); 

那么这就是我现在在TextWatcher函数中所具有的function,我不确定我的代码应该在哪个函数中:

 @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) { } 

这是一个logging输出的样本,所以我知道格式正在工作:

 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 

这里是输出的图像(顶端EditText是phoneNumberText,底部是testPhoneNumberText): http ://imgur.com/GXwRu.png

我想知道的是,如何将格式化的输出重新input原始EditText中,因为它正在input? 当我尝试去做,奇怪的事情发生像重复,或者只是表明它没有格式化。 我试过使用s.replace(),但我不知道我正确使用它。 这可能吗? 谢谢?

Solutions Collecting From Web of "如何在Android应用程序中使用AsYouTypeFormatter TextWatcher?"

我结束了在顶部声明一个新的string:

 private String unformattedPhoneNumber; 

然后改变我的代码:

 @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; } 

}

似乎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; } 

对于那些只想在用户input时在EditText中格式化用户input的电话号码的人来说,使用PhoneNumberFormattingTextWatcher (内置于Android)比尝试任何这些详细的答案要容易得多 – 而且它的一行码!

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

您也可以传递用户select的区域,我认为这个区域实际上会回答OP的问题,但是直到API 21:

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