简体   繁体   English

在 Android 中格式化 EditText 的电话号码

[英]Phone number formatting an EditText in Android

I am making a simple Address Book app (targeting 4.2) that takes name, address, city, state, zip and phone.我正在制作一个简单的地址簿应用程序(针对 4.2),它需要姓名、地址、城市、州、邮政编码和电话。

I want to format the phone number input as a phone number (XXX) XXX-XXXX, but I need to pull the value out as a string so I can store it in my database when I save.我想将输入的电话号码格式化为电话号码 (XXX) XXX-XXXX,但我需要将该值作为字符串提取出来,以便在保存时将其存储在我的数据库中。 How can i do this??我怎样才能做到这一点?? I have the EditText set for "phone number" input but that obviously doesn't do too much.我为“电话号码”输入设置了 EditText ,但这显然不会做太多。

Simply use the PhoneNumberFormattingTextWatcher , just call:只需使用PhoneNumberFormattingTextWatcher ,只需调用:

editText.addTextChangedListener(new PhoneNumberFormattingTextWatcher());

Addition添加
To be clear, PhoneNumberFormattingTextWatcher's backbone is the PhoneNumberUtils class.明确地说,PhoneNumberFormattingTextWatcher 的主干是 PhoneNumberUtils 类。 The difference is the TextWatcher maintains the EditText while you must call PhoneNumberUtils.formatNumber() every time you change its contents.不同之处在于 TextWatcher 维护 EditText,而您每次更改其内容时都必须调用PhoneNumberUtils.formatNumber()

There is a library called PhoneNumberUtils that can help you to cope with phone number conversions and comparisons.有一个名为PhoneNumberUtils的库可以帮助您处理电话号码转换和比较。 For instance, use ...例如,使用...

EditText text = (EditText) findViewById(R.id.editTextId);
PhoneNumberUtils.formatNumber(text.getText().toString())

... to format your number in a standard format. ...以标准格式格式化您的号码。

PhoneNumberUtils.compare(String a, String b);

... helps with fuzzy comparisons. ...有助于模糊比较。 There are lots more.还有很多。 Check out http://developer.android.com/reference/android/telephony/PhoneNumberUtils.html for more.查看http://developer.android.com/reference/android/telephony/PhoneNumberUtils.html了解更多信息。

ps setting the the EditText to phone is already a good choice; ps 将EditText 设置为phone已经是一个不错的选择; eventually it might be helpful to add digits eg in your layout it looks as ...最终添加digits可能会有所帮助,例如在您的布局中,它看起来像......

<EditText
    android:id="@+id/editTextId"
    android:inputType="phone"
    android:digits="0123456789+" 
/> 

Simply Use This :只需使用这个:

In Java Code :在 Java 代码中:

editText.addTextChangedListener(new PhoneNumberFormattingTextWatcher());

In XML Code :在 XML 代码中:

<EditText
    android:id="@+id/etPhoneNumber"
    android:inputType="phone"/>

This code work for me.这段代码对我有用。 It'll auto format when text changed in edit text.当编辑文本中的文本更改时,它将自动格式化。

I've recently done a similar formatting like 1 (XXX) XXX-XXXX for Android EditText.我最近为 Android EditText 完成了类似的格式设置,例如 1 (XXX) XXX-XXXX。 Please find the code below.请在下面找到代码。 Just use the TextWatcher sub-class as the text changed listener : ....只需使用 TextWatcher 子类作为文本更改侦听器:....

UsPhoneNumberFormatter addLineNumberFormatter = new UsPhoneNumberFormatter(
            new WeakReference<EditText>(mYourEditText));
    mYourEditText.addTextChangedListener(addLineNumberFormatter);

... ...

private class UsPhoneNumberFormatter implements TextWatcher {
    //This TextWatcher sub-class formats entered numbers as 1 (123) 456-7890
    private boolean mFormatting; // this is a flag which prevents the
                                    // stack(onTextChanged)
    private boolean clearFlag;
    private int mLastStartLocation;
    private String mLastBeforeText;
    private WeakReference<EditText> mWeakEditText;

    public UsPhoneNumberFormatter(WeakReference<EditText> weakEditText) {
        this.mWeakEditText = weakEditText;
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count,
            int after) {
        if (after == 0 && s.toString().equals("1 ")) {
            clearFlag = true;
        }
        mLastStartLocation = start;
        mLastBeforeText = s.toString();
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before,
            int count) {
        // TODO: Do nothing
    }

    @Override
    public void afterTextChanged(Editable s) {
        // Make sure to ignore calls to afterTextChanged caused by the work
        // done below
        if (!mFormatting) {
            mFormatting = true;
            int curPos = mLastStartLocation;
            String beforeValue = mLastBeforeText;
            String currentValue = s.toString();
            String formattedValue = formatUsNumber(s);
            if (currentValue.length() > beforeValue.length()) {
                int setCusorPos = formattedValue.length()
                        - (beforeValue.length() - curPos);
                mWeakEditText.get().setSelection(setCusorPos < 0 ? 0 : setCusorPos);
            } else {
                int setCusorPos = formattedValue.length()
                        - (currentValue.length() - curPos);
                if(setCusorPos > 0 && !Character.isDigit(formattedValue.charAt(setCusorPos -1))){
                    setCusorPos--;
                }
                mWeakEditText.get().setSelection(setCusorPos < 0 ? 0 : setCusorPos);
            }
            mFormatting = false;
        }
    }

    private String formatUsNumber(Editable text) {
        StringBuilder formattedString = new StringBuilder();
        // Remove everything except digits
        int p = 0;
        while (p < text.length()) {
            char ch = text.charAt(p);
            if (!Character.isDigit(ch)) {
                text.delete(p, p + 1);
            } else {
                p++;
            }
        }
        // Now only digits are remaining
        String allDigitString = text.toString();

        int totalDigitCount = allDigitString.length();

        if (totalDigitCount == 0
                || (totalDigitCount > 10 && !allDigitString.startsWith("1"))
                || totalDigitCount > 11) {
            // May be the total length of input length is greater than the
            // expected value so we'll remove all formatting
            text.clear();
            text.append(allDigitString);
            return allDigitString;
        }
        int alreadyPlacedDigitCount = 0;
        // Only '1' is remaining and user pressed backspace and so we clear
        // the edit text.
        if (allDigitString.equals("1") && clearFlag) {
            text.clear();
            clearFlag = false;
            return "";
        }
        if (allDigitString.startsWith("1")) {
            formattedString.append("1 ");
            alreadyPlacedDigitCount++;
        }
        // The first 3 numbers beyond '1' must be enclosed in brackets "()"
        if (totalDigitCount - alreadyPlacedDigitCount > 3) {
            formattedString.append("("
                    + allDigitString.substring(alreadyPlacedDigitCount,
                            alreadyPlacedDigitCount + 3) + ") ");
            alreadyPlacedDigitCount += 3;
        }
        // There must be a '-' inserted after the next 3 numbers
        if (totalDigitCount - alreadyPlacedDigitCount > 3) {
            formattedString.append(allDigitString.substring(
                    alreadyPlacedDigitCount, alreadyPlacedDigitCount + 3)
                    + "-");
            alreadyPlacedDigitCount += 3;
        }
        // All the required formatting is done so we'll just copy the
        // remaining digits.
        if (totalDigitCount > alreadyPlacedDigitCount) {
            formattedString.append(allDigitString
                    .substring(alreadyPlacedDigitCount));
        }

        text.clear();
        text.append(formattedString.toString());
        return formattedString.toString();
    }

}

Maybe below sample project helps you;也许下面的示例项目可以帮助您;

https://github.com/reinaldoarrosi/MaskedEditText https://github.com/reinaldoarrosi/MaskedEditText

That project contains a view class call MaskedEditText .该项目包含一个视图类调用MaskedEditText As first, you should add it in your project .首先,您应该将它添加到您的项目中

Then you add below xml part in res/values/attrs.xml file of project;然后在项目的 res/values/attrs.xml 文件中添加以下 xml 部分;

<resources>
    <declare-styleable name="MaskedEditText">
        <attr name="mask" format="string" />
        <attr name="placeholder" format="string" />
    </declare-styleable>
</resources>

Then you will be ready to use MaskedEditText view.然后您就可以使用MaskedEditText视图了。

As last, you should add MaskedEditText in your xml file what you want like below;最后,您应该在您的 xml 文件中添加 MaskedEditText,如下所示;

<packagename.currentfolder.MaskedEditText
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/maskedEditText"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ems="10"
    android:text="5"
    app:mask="(999) 999-9999"
    app:placeholder="_" >

Of course that, you can use it programmatically.当然,您可以以编程方式使用它。

After those steps, adding MaskedEditText will appear like below;完成这些步骤后,添加MaskedEditText将如下所示;

在此处输入图片说明

As programmatically, if you want to take it's text value as unmasked, you may use below row;以编程方式,如果您想将其文本值设为未屏蔽,您可以使用下面的行;

maskedEditText.getText(true);

To take masked value, you may send false value instead of true value in the getText method.要获取掩码值,您可以在getText方法中发送false值而不是true值。

You need to create a class:您需要创建一个类:

public class PhoneTextFormatter implements TextWatcher {

    private final String TAG = this.getClass().getSimpleName();

    private EditText mEditText;

    private String mPattern;

    public PhoneTextFormatter(EditText editText, String pattern) {
        mEditText = editText;
        mPattern = pattern;
        //set max length of string
        int maxLength = pattern.length();
        mEditText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)});
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        StringBuilder phone = new StringBuilder(s);

        Log.d(TAG, "join");

        if (count > 0 && !isValid(phone.toString())) {
            for (int i = 0; i < phone.length(); i++) {
                Log.d(TAG, String.format("%s", phone));
                char c = mPattern.charAt(i);

                if ((c != '#') && (c != phone.charAt(i))) {
                    phone.insert(i, c);
                }
            }

            mEditText.setText(phone);
            mEditText.setSelection(mEditText.getText().length());
        }
    }

    @Override
    public void afterTextChanged(Editable s) {

    }

    private boolean isValid(String phone)
    {
        for (int i = 0; i < phone.length(); i++) {
            char c = mPattern.charAt(i);

            if (c == '#') continue;

            if (c != phone.charAt(i)) {
                return false;
            }
        }

        return true;
    }
}

Use this as follows:使用方法如下:

phone = view.findViewById(R.id.phone);
phone.addTextChangedListener(new PhoneTextFormatter(phone, "+7 (###) ###-####"));

Follow the instructions in this Answer to format the EditText mask.按照此答案中的说明设置 EditText 掩码的格式。

https://stackoverflow.com/a/34907607/1013929 https://stackoverflow.com/a/34907607/1013929

And after that, you can catch the original numbers from the masked string with:之后,您可以使用以下命令从掩码字符串中捕获原始数字:

String phoneNumbers = maskedString.replaceAll("[^\\d]", "");
//(123) 456 7890  formate set

private int textlength = 0;

public class MyPhoneTextWatcher implements TextWatcher {

    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    }
    @Override
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {


        String text = etMobile.getText().toString();
        textlength = etMobile.getText().length();

        if (text.endsWith(" "))
            return;

        if (textlength == 1) {
            if (!text.contains("(")) {
                etMobile.setText(new StringBuilder(text).insert(text.length() - 1, "(").toString());
                etMobile.setSelection(etMobile.getText().length());
            }

        } else if (textlength == 5) {

            if (!text.contains(")")) {
                etMobile.setText(new StringBuilder(text).insert(text.length() - 1, ")").toString());
                etMobile.setSelection(etMobile.getText().length());
            }

        } else if (textlength == 6 || textlength == 10) {
            etMobile.setText(new StringBuilder(text).insert(text.length() - 1, " ").toString());
            etMobile.setSelection(etMobile.getText().length());
        }

    }
    @Override
    public void afterTextChanged(Editable editable) {
    }
}

More like clean:更喜欢干净:

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {

String text = etyEditText.getText();
    int textlength = etyEditText.getText().length();

    if (text.endsWith("(") ||text.endsWith(")")|| text.endsWith(" ") || text.endsWith("-")  )
                return;

    switch (textlength){
        case 1:
            etyEditText.setEditText(new StringBuilder(text).insert(text.length() - 1, "(").toString());
            etyEditText.setSelection(etyEditText.getText().length());
            break;
        case 5:
            etyEditText.setEditText(new StringBuilder(text).insert(text.length() - 1, ")").toString());
            etyEditText.setSelection(etyEditText.getText().length());
            break;
        case 6:
            etyEditText.setEditText(new StringBuilder(text).insert(text.length() - 1, " ").toString());
            etyEditText.setSelection(etyEditText.getText().length());
            break;
        case 10:
            etyEditText.setEditText(new StringBuilder(text).insert(text.length() - 1, "-").toString());
            etyEditText.setSelection(etyEditText.getText().length());
            break;
    }

}

You can use a Regular Expression with pattern matching to extract number from a string.您可以使用具有模式匹配的正则表达式从字符串中提取数字。

    String s="";
    Pattern p = Pattern.compile("\\d+");
    Matcher m = p.matcher("(1111)123-456-789"); //editText.getText().toString()                                      
    while (m.find()) {
    s=s+m.group(0);
    }
    System.out.println("............"+s);    

    Output : ............1111123456789

If you're only interested in international numbers and you'd like to be able to show the flag of the country that matches the country code in the input, I wrote a small library for that:如果您只对国际号码感兴趣,并且希望能够显示与输入中的国家/地区代码匹配的国家/地区的国旗,我为此编写了一个小型库:

https://github.com/tfcporciuncula/phonemoji https://github.com/tfcporciuncula/phonemoji

Here's how it looks:这是它的外观:

图书馆演示

Don't worry.别担心。 I have make a most of better solution for you.我已经为你做了一个更好的解决方案。 You can see this simple app link below.您可以在下面看到这个简单的应用程序链接。

private EditText mPasswordField;
public int textLength = 0;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mPasswordField = (EditText) findViewById(R.id.password_field);
    mPasswordField.addTextChangedListener(this);
}

@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {


    String text = mPasswordField.getText().toString();
    textLength = mPasswordField.getText().length();

    if (text.endsWith("-") || text.endsWith(" ") || text.endsWith(" "))
        return;

    if (textLength == 1) {
        if (!text.contains("(")) {
            mPasswordField.setText(new StringBuilder(text).insert(text.length() - 1, "(").toString());
            mPasswordField.setSelection(mPasswordField.getText().length());
        }

    } else if (textLength == 5) {

        if (!text.contains(")")) {
            mPasswordField.setText(new StringBuilder(text).insert(text.length() - 1, ")").toString());
            mPasswordField.setSelection(mPasswordField.getText().length());
        }

    } else if (textLength == 6) {
            mPasswordField.setText(new StringBuilder(text).insert(text.length() - 1, " ").toString());
            mPasswordField.setSelection(mPasswordField.getText().length());

    } else if (textLength == 10) {
        if (!text.contains("-")) {
            mPasswordField.setText(new StringBuilder(text).insert(text.length() - 1, "-").toString());
            mPasswordField.setSelection(mPasswordField.getText().length());
        }
    } else if (textLength == 15) {
        if (text.contains("-")) {
            mPasswordField.setText(new StringBuilder(text).insert(text.length() - 1, "-").toString());
            mPasswordField.setSelection(mPasswordField.getText().length());
        }
    }else if (textLength == 18) {
        if (text.contains("-")) {
            mPasswordField.setText(new StringBuilder(text).insert(text.length() - 1, "-").toString());
            mPasswordField.setSelection(mPasswordField.getText().length());
        }
    } else if (textLength == 20) {
        Intent i = new Intent(MainActivity.this, Activity2.class);
        startActivity(i);

    }



}

@Override
public void afterTextChanged(Editable s) {

}

Not: Don't forget "implement TextWatcher" with your activity class.不是:不要忘记在您的活动类中“实现 TextWatcher”。

Link : https://drive.google.com/open?id=0B-yo9VvU7jyBMjJpT29xc2k5bnc链接: https : //drive.google.com/open?id=0B-yo9VvU7jyBMjJpT29xc2k5bnc

Hope you are feeling cool for this solution.希望您对这个解决方案感到很酷。

You can use spawns to format phone numbers in Android.您可以使用 spawn 来格式化 Android 中的电话号码。 This solution is better than the others because it does not change input text.此解决方案比其他解决方案更好,因为它不会更改输入文本。 Formatting remains purely visual.格式仍然纯粹是视觉上的。

implementation 'com.googlecode.libphonenumber:libphonenumber:7.0.4'

Formatter class:格式化程序类:

open class PhoneNumberFormatter : TransformationMethod {
private val mFormatter: AsYouTypeFormatter = PhoneNumberUtil.getInstance().getAsYouTypeFormatter(Locale.getDefault().country)

override fun getTransformation(source: CharSequence, view: View): CharSequence {
    val formatted = format(source)
    if (source is Spannable) {
        setSpans(source, formatted)
        return source
    }
    return formatted
}
override fun onFocusChanged(view: View?, sourceText: CharSequence?, focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) = Unit

private fun setSpans(spannable: Spannable, formatted: CharSequence): CharSequence {

    spannable.clearSpawns()

    var charterIndex = 0
    var formattedIndex = 0
    var spawn = ""
    val spawns: List<String> = spannable
        .map {
            spawn = ""
            charterIndex = formatted.indexOf(it, formattedIndex)
            if (charterIndex != -1){
                spawn = formatted.substring(formattedIndex, charterIndex-1)
                formattedIndex = charterIndex+1
            }
            spawn
        }

    spawns.forEachIndexed { index, sequence ->
        spannable.setSpan(CharterSpan(sequence), index, index + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
    }

    return formatted
}

private fun Spannable.clearSpawns() =
    this
        .getSpans(0, this.length, CharterSpan::class.java)
        .forEach { this.removeSpan(it) }

private fun format(spannable: CharSequence): String {
    mFormatter.clear()
    var formated = ""
    for (i in 0 until spannable.length) {
        formated = mFormatter.inputDigit(spannable[i])
    }
    return formated
}

private inner class CharterSpan(private val charters: String) : ReplacementSpan() {

    var space = 0

    override fun getSize(paint: Paint, text: CharSequence, start: Int, end: Int, fm: Paint.FontMetricsInt?): Int {
        space = Math.round(paint.measureText(charters, 0, charters.length))
        return Math.round(paint.measureText(text, start, end)) + space
    }

    override fun draw(canvas: Canvas, text: CharSequence, start: Int, end: Int, x: Float, top: Int, y: Int, bottom: Int, paint: Paint) {
        space = Math.round(paint.measureText(charters, 0, charters.length))
        canvas.drawText(text, start, end, x + space, y.toFloat(), paint)
        canvas.drawText(charters, x, y.toFloat(), paint)
    }
    }

}

Uasge:用法:

editText.transformationMethod = formatter

You can accept only numbers and phone number type using java code您只能接受使用 java 代码的数字和电话号码类型

 EditText number1 = (EditText) layout.findViewById(R.id.edittext); 
    number1.setInputType(InputType.TYPE_CLASS_NUMBER|InputType.TYPE_CLASS_PHONE);
     number1.setKeyListener(DigitsKeyListener.getInstance("0123456789”));
      number1.setFilters(new InputFilter[] {new InputFilter.LengthFilter(14)}); // 14 is max digits

This code will avoid lot of validations after reading input此代码将避免在读取输入后进行大量验证

TelephonyManager manager = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
String CountryID= manager.getSimCountryIso().toUpperCase();
try{
    PhoneNumberUtil pnu = PhoneNumberUtil.getInstance();
    Phonenumber.PhoneNumber pn1 = pnu.parse("99", CountryID);
    String pnE1641 = pnu.format(pn1, PhoneNumberUtil.PhoneNumberFormat.E164);
    code = pnE1641.substring(0, pnE1641.length()-2);
    codeLength  = code.length();
    Log.e("dfdsfdsfsdfsdf", "onCreate: "+codeLength);

}catch (Exception e){
    Log.e("dfdsfdsfsdfsdf", "onCreate: "+e);
}

phoneEditText.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        int digits = phoneEditText.getText().toString().length();
        if (digits > 1)
            lastChar = phoneEditText.getText().toString().substring(digits-1);
    }
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        int digits = phoneEditText.getText().toString().length();
        Log.d("LENGTH",""+digits);
        if (!lastChar.equals("-")) {
            if (digits == codeLength+6) {
                phoneEditText.append("-");
            }
        }
    }
    @Override
    public void afterTextChanged(Editable s) {
        if (!s.toString().startsWith("("+code+") ")) {
            phoneEditText.setText("("+code+") ");
            Selection.setSelection(phoneEditText.getText(), phoneEditText.getText().length());
        }
    }
});

This code is work for me for (216) 555-5555此代码适用于 (216) 555-5555

etphonenumber.addTextChangedListener(new TextWatcher()
        {
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count)
            {
                // TODO Auto-generated method stub
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after)
            {
                // TODO Auto-generated method stub
            }
            @Override
            public void afterTextChanged(Editable s)
            {
                String text = etphonenumber.getText().toString();
                int  textLength = etphonenumber.getText().length();
                if (text.endsWith("-") || text.endsWith(" ") || text.endsWith(" "))
                    return;
                if (textLength == 1) {
                    if (!text.contains("("))
                    {
                        etphonenumber.setText(new StringBuilder(text).insert(text.length() - 1, "(").toString());
                        etphonenumber.setSelection(etphonenumber.getText().length());
                    }
                }
                else if (textLength == 5)
                {
                    if (!text.contains(")"))
                    {
                        etphonenumber.setText(new StringBuilder(text).insert(text.length() - 1, ")").toString());
                        etphonenumber.setSelection(etphonenumber.getText().length());
                    }
                }
                else if (textLength == 6)
                {
                    etphonenumber.setText(new StringBuilder(text).insert(text.length() - 1, " ").toString());
                    etphonenumber.setSelection(etphonenumber.getText().length());
                }
                else if (textLength == 10)
                {
                    if (!text.contains("-"))
                    {
                        etphonenumber.setText(new StringBuilder(text).insert(text.length() - 1, "-").toString());
                        etphonenumber.setSelection(etphonenumber.getText().length());
                    }
                }
            }
        });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM