【问题标题】:How do I use AsYouTypeFormatter TextWatcher in Android App?如何在 Android 应用程序中使用 AsYouTypeFormatter TextWatcher?
【发布时间】:2012-12-18 01:04:12
【问题描述】:

我正在尝试将 Google 的 libphonenumber 中的 AsYouTypeFormatter 与 TextWatcher 一起使用,但不确定是否可行。我已经能够将文本格式化为从 EditText 字段中输入的格式,并将其输出到另一个 EditText 中,但无法直接更改原始的 EditText 字段(这是我想要的)。我知道 phoneNumberFormattingTextWatcher,但我们希望用户能够最终选择他们所在的区域设置,并且比使用允许的区域拥有更多的控制权(根据我收集的信息)。

一流的:

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

首先我在班级顶部初始化 AsYouTypeFormatter:

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

在创建标签等之后,我创建一个 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 函数中所拥有的,但我不确定我的代码应该在这些函数中的哪一个:

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

这是一个记录输出的示例,所以我知道格式可以正常工作:

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

我想知道的是如何在输入时将格式化的输出恢复到原始的 EditText 中?当我尝试这样做时,会发生奇怪的事情,例如重复,或者只是显示它未格式化。我试过使用 s.replace() 但我不确定我是否正确使用它。这可能吗?谢谢?

【问题讨论】:

  • 为什么不直接使用PhoneNumberFormattingTextWatcher(String countryCode)??? stackoverflow.com/a/29109236/1103584
  • 这需要 minSdkVersion 21
  • @sugarwaffle 我遇到了和你一样的问题。当用户键入时,如何使文本格式化? AsYouTypeFormatter 似乎没有做任何事情。之后我不想格式化,我想在输入电话号码时进行格式化。有什么解决办法吗?

标签: java android android-edittext phone-number textwatcher


【解决方案1】:

对于那些只想在用户键入时在 EditText 中格式化用户输入的电话号码的其他人,使用PhoneNumberFormattingTextWatcher(内置于 Android)比尝试任何这些冗长的答案要容易得多 -这是一行代码!

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

您还可以传递用户选择的区域,我认为这实际上会回答 OP 的问题,但直到 API 21 才可用:

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

【讨论】:

  • 这需要你声明 minSdkVersion 21,这可能不是现在大多数项目的选项
  • @LouisMorda 仅通过区域所需的 minSdkVersion 21 - 您可以通过其他方式(就像我在我的项目中所做的那样)跟踪区域以支持较低的 minSdkVersion,我只是指出它是可用。
  • 根据其他几篇 SOF 帖子和我自己的个人经验,这仅适用于有限数量的设备。为什么,我不知道。
  • PhoneNumberFormattingTextWatcher 不允许您更改号码的格式。我当前的项目需要一个格式为:###-###-#### 的电话号码,PhoneNumberFormattingTextWatcher 不允许。
【解决方案2】:

我最终在顶部声明了一个新字符串:

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

【讨论】:

  • 我无法添加特殊字符,例如 +,(,) 等...怎么办?
  • 您不应该使用此格式化程序添加 +, (, ),它应该为您添加它。你能澄清一下你想要做什么吗?
  • 假设用户尝试输入带有预期字符的数字,我认为它应该接受它:)
  • 目前它应该允许用户输入这些字符但删除它们。据我所知,AYTF 不接受带有这些字符的部分格式化电话号码,它作为无效电话号码返回,并且不知道如何格式化它们。
  • 这段代码看起来像是对 AsYouTypeFormatter 的滥用,您是否查看过它的源代码或联系任何维护人员了解如何使用它?从项目网站上看起来,该代码自 Ice Cream Sandwhich “自 4.0(Ice Cream Sandwich)以来被 Android 框架使用”以来已包含在 Android 中。 - code.google.com/p/libphonenumber
猜你喜欢
  • 2012-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 2012-10-04
  • 2014-05-24
  • 2011-06-07
  • 1970-01-01
相关资源
最近更新 更多