16

I have an EditText view and I want it to format the user's input into the phone number format. For example, when the user types in 1234567890, the EditText view should dynamically show it as "(123) 456-7890" as soon as the first 3 numbers are inputted.

I tried the following in my OnCreate but it didn't seem to do anything for me...

EditText ET = (EditText) findViewById(R.id.add_number);
ET.addTextChangedListener(new PhoneNumberFormattingTextWatcher());

How can I get the user's input to display in the phone number format?

Pang
  • 9,564
  • 146
  • 81
  • 122
thedeepfield
  • 6,138
  • 25
  • 72
  • 107

8 Answers8

46

With this code you can make a custom TextWatcher and make any format you desire:

ET.addTextChangedListener(new PhoneNumberFormattingTextWatcher() {
        //we need to know if the user is erasing or inputing some new character
        private boolean backspacingFlag = false;
        //we need to block the :afterTextChanges method to be called again after we just replaced the EditText text
        private boolean editedFlag = false;
        //we need to mark the cursor position and restore it after the edition
        private int cursorComplement;

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            //we store the cursor local relative to the end of the string in the EditText before the edition
            cursorComplement = s.length()-ET.getSelectionStart();
            //we check if the user ir inputing or erasing a character
            if (count > after) {
                backspacingFlag = true;
            } else {
                backspacingFlag = false;
            }
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            // nothing to do here =D
        }

        @Override
        public void afterTextChanged(Editable s) {
            String string = s.toString();
            //what matters are the phone digits beneath the mask, so we always work with a raw string with only digits
            String phone = string.replaceAll("[^\\d]", "");

            //if the text was just edited, :afterTextChanged is called another time... so we need to verify the flag of edition
            //if the flag is false, this is a original user-typed entry. so we go on and do some magic
            if (!editedFlag) {

                //we start verifying the worst case, many characters mask need to be added
                //example: 999999999 <- 6+ digits already typed
                // masked: (999) 999-999
                if (phone.length() >= 6 && !backspacingFlag) {
                    //we will edit. next call on this textWatcher will be ignored
                    editedFlag = true;
                    //here is the core. we substring the raw digits and add the mask as convenient
                    String ans = "(" + phone.substring(0, 3) + ") " + phone.substring(3,6) + "-" + phone.substring(6);
                    ET.setText(ans);
                    //we deliver the cursor to its original position relative to the end of the string
                    ET.setSelection(ET.getText().length()-cursorComplement);

                //we end at the most simple case, when just one character mask is needed
                //example: 99999 <- 3+ digits already typed
                // masked: (999) 99
                } else if (phone.length() >= 3 && !backspacingFlag) {
                    editedFlag = true;
                    String ans = "(" +phone.substring(0, 3) + ") " + phone.substring(3);
                    ET.setText(ans);
                    ET.setSelection(ET.getText().length()-cursorComplement);
                }
            // We just edited the field, ignoring this cicle of the watcher and getting ready for the next
            } else {
                editedFlag = false;
            }
        }
    });

Ensure to limit the EditText Lenght in XML to 14 characters

<EditText
    android:id="@+id/editText_phone"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:inputType="phone"
    android:lines="1"
    android:maxLength="14"/>
Ziem
  • 6,579
  • 8
  • 53
  • 86
Maurício Fonseca
  • 1,006
  • 1
  • 9
  • 9
11

Step 1: Here the code for input field in XML file.

 <EditText
    android:id="@+id/editText_phone"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:inputType="phone"
    android:lines="1"
    android:maxLength="14"/>

Step 2: Here is the code add into the MainFile.java

 phoneNo = (EditText)findViewById(R.id.editText_phone);
 phoneNo.addTextChangedListener(new PhoneNumberFormattingTextWatcher());

Output: It will give you the number like (123)456-7890

Yogesh Shinde
  • 393
  • 4
  • 11
5

Try this

The PhoneNumberFormattingTextWatcher() method was not working i tried allot finally i get the solutions

  1. In your xml file paste this

    <EditText
    android:id="@+id/editTextId"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:inputType="phone"
    android:digits="0123456789+" />
    
  2. in your oncreate method paste this

    final EditText editText = (EditText) findViewById(R.id.editTextId);
    editText.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 = editText.getText().toString();
            int  textLength = editText.getText().length();
            if (text.endsWith("-") || text.endsWith(" ") || text.endsWith(" "))
                return;
            if (textLength == 1) {
                if (!text.contains("("))
                {
                    editText.setText(new StringBuilder(text).insert(text.length() - 1, "(").toString());
                    editText.setSelection(editText.getText().length());
                }
            }
            else if (textLength == 5)
            {
                if (!text.contains(")"))
                {
                    editText.setText(new StringBuilder(text).insert(text.length() - 1, ")").toString());
                    editText.setSelection(editText.getText().length());
                }
            }
            else if (textLength == 6)
            {
                editText.setText(new StringBuilder(text).insert(text.length() - 1, " ").toString());
                editText.setSelection(editText.getText().length());
            }
            else if (textLength == 10)
            {
                if (!text.contains("-"))
                {
                    editText.setText(new StringBuilder(text).insert(text.length() - 1, "-").toString());
                    editText.setSelection(editText.getText().length());
                }
            }
            else if (textLength == 15)
            {
                if (text.contains("-"))
                {
                    editText.setText(new StringBuilder(text).insert(text.length() - 1, "-").toString());
                    editText.setSelection(editText.getText().length());
                }
            }
            else if (textLength == 18)
            {
                if (text.contains("-"))
                {
                    editText.setText(new StringBuilder(text).insert(text.length() - 1, "-").toString());
                    editText.setSelection(editText.getText().length());
                }
            }
        }
    });
    

OUTPUT:- enter image description here

Community
  • 1
  • 1
Sunil
  • 3,785
  • 1
  • 32
  • 43
2

I did a combination of things, i modified my input type to phone, then I used regex to remove all non numeric characters: phonenumber = phonenumber.replaceAll("\D", "");

thedeepfield
  • 6,138
  • 25
  • 72
  • 107
0

In your layout, set the input mode to "phone"

http://developer.android.com/reference/android/widget/TextView.html#attr_android:inputMethod http://developer.android.com/reference/android/text/InputType.html#TYPE_CLASS_PHONE

<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:inputType="phone" />

If this doesn't quite suit your needs, add a listener to your EditText and format the text manually on each keystroke.

    editText.setOnKeyListener(new OnKeyListener() {

        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (event.getAction() == KeyEvent.ACTION_UP) {
                // format your EditText here
            }
            return false;
        }
    });
invertigo
  • 6,336
  • 5
  • 39
  • 64
  • This edit text is where the user inputs their number and saves it to a database. I have my inputType="number". If I have it set to phone, it will be written in the format (123) 456-7890, which I don't want. I just want the edittext view to mask the input, not actually format it. Is that something that is possible? – thedeepfield Feb 04 '13 at 18:25
  • in that case, i'd say store a local variable with the number, and let the edittext string get formatting as you see fit. – invertigo Feb 04 '13 at 18:40
0

In your Java code you can use

yourEditText.setInputType(InputTytpe.TYPE_CLASS_PHONE)

or in your xml

android:inputType="phone"

Java

XML

codeMagic
  • 44,549
  • 13
  • 77
  • 93
  • will this just mask the EditText View or will it actually format the users input? I just want to mask the input as this editview is used to store user input into a database. I need the input to only be numbers. – thedeepfield Feb 04 '13 at 18:27
  • Oh, that's different...it will format it. Format it this way then use the string functions `split` and `trim` to get out only the numbers – codeMagic Feb 04 '13 at 20:22
  • or with `addTextChanged` store the character in a string variable if it is a number and append each number to the string – codeMagic Feb 04 '13 at 20:28
0

please find below code:
I used TextWatcher interface to format inputted phone number into (XXX) XXX-XXXX dynamically.

UsPhoneNumberFormatter addLineNumberFormatter = new UsPhoneNumberFormatter(edittxtPhoneNo);
edittxtPhoneNo.addTextChangedListener(addLineNumberFormatter);  


public class UsPhoneNumberFormatter implements TextWatcher {
    private EditText etMobile;

    public UsPhoneNumberFormatter(EditText edt) {
        etMobile = edt;
    }

    @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();
        int 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) {
            if (!text.contains(" ")) {
                etMobile.setText(new StringBuilder(text).insert(text.length() - 1, " ").toString());
                etMobile.setSelection(etMobile.getText().length());
            }
        } else if (textlength == 10) {
            if (!text.contains("-")) {
                etMobile.setText(new StringBuilder(text).insert(text.length() - 1, "-").toString());
                etMobile.setSelection(etMobile.getText().length());
            }
        }
    }

    @Override
    public void afterTextChanged(Editable editable) {
    }
}
Neelesh Atale
  • 526
  • 4
  • 12
-7

You could either do this with JQuery validate (onkeyup event) so you could do dynamic formatting as they type (jarring experience there to contemplate) - or you could do it with a MVVM library such as RAZOR or KnockoutJS (as they exit the field).

Examples of what you want to do are both on the JQuery Validate documentation site, as well as the knockout JS site.