14

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()を使用してみましたが、正しく使用しているかどうかわかりません。これは可能ですか?ありがとう?

4

2 に答える 2

11

ユーザーが入力した電話番号をユーザーが入力したときにEditTextにフォーマットしたいだけの人にとってはPhoneNumberFormattingTextWatcher、これらの詳細な回答を試すよりもはるかに使いやすく(Androidに組み込まれています)、1行のコードです!!

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

ユーザーが選択したリージョンを渡すこともできます。これは実際にはOPの質問に答えると思いますが、API21まで利用できませんでした。

//This version takes a country code!
this.editText.addTextChangedListener(new PhoneNumberFormattingTextWatcher("US"));
于 2015-03-17T20:40:19.400 に答える
5

私は最終的に上部に新しい文字列を宣言しました:

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;
}
于 2013-01-03T19:04:09.977 に答える