11

Instead of 5118710, it should be 511-8710. I'd like to add a dash after the user the user inputted 3 digits already in the EditText. The maximum length of the EditText is 7 digits only.

After I figured out the above problem, I've got stuck in coding again. When I already inputted 3 digits, it appends dash (that's what I'd like to happen) but my problem here is that the next 3 digits also appends dash (Like this: 511-871-)... Please help me with this. thanks!

    txt_HomeNo.addTextChangedListener(new TextWatcher() {

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

            boolean flag = true;
            String eachBlock[] = txt_HomeNo.getText().toString().split("-");
            for (int i = 0; i < eachBlock.length; i++) {
                if (eachBlock[i].length() > 3) {
                    flag = false;
                }
            }

            if (flag) {

                txt_HomeNo.setOnKeyListener(new OnKeyListener() {

                    @Override
                    public boolean onKey(View v, int keyCode, KeyEvent event) {

                        if (keyCode == KeyEvent.KEYCODE_DEL)
                            keyDel = 1;
                        return false;
                    }
                });

                if (keyDel == 0) {

                    if (((txt_HomeNo.getText().length() + 1) % 4) == 0) {

                        if (txt_HomeNo.getText().toString().split("-").length <= 3) {
                            txt_HomeNo.setText(txt_HomeNo.getText() + "-");
                            txt_HomeNo.setSelection(txt_HomeNo.getText().length());
                        }
                    }
                    a = txt_HomeNo.getText().toString();
                } else {
                    a = txt_HomeNo.getText().toString();
                    keyDel = 0;
                }

            } else {
                txt_HomeNo.setText(a);
            }

        }
  • Have a look at [custom format edit text input](http://stackoverflow.com/questions/5947674/custom-format-edit-text-input-android) – neo108 Jun 07 '13 at 02:31
  • Thanks @neo108 however, how can I make it like "3digits-4digits" since the logic of the code is set on 4digits-4digits? –  Jun 07 '13 at 03:21
  • Can you please post the code that you have at the moment to format the digits. – neo108 Jun 07 '13 at 04:33
  • Hi neo108 please refer above for my codes. Thanks! –  Jun 07 '13 at 04:59
  • http://stackoverflow.com/questions/4172242/live-editing-of-users-input/37187857#37187857 – HenryChuang May 12 '16 at 13:11

7 Answers7

37

The most straightforward solution is to use PhoneNumberFormattingTextWatcher which will format the number according to the system locale.

XML:

<EditText
    android:id="@+id/phone_number"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="@string/enter_phone_number"
    android:inputType="phone" />

Add addTextChangedListener() in your class:

EditText phoneNumber = (EditText)findViewById(R.id.phone_number);
phoneNumber.addTextChangedListener(new PhoneNumberFormattingTextWatcher());
ozbek
  • 20,955
  • 5
  • 61
  • 84
11

Implement the following modified addTextChangedListener for txt_HomeNo. The code below is checking if the length of the text entered is 3 and if it is then add the - to it. Not a very robust solution but it works!

txt_HomeNo.addTextChangedListener(new TextWatcher() {

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

        txt_HomeNo.setOnKeyListener(new OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {

                if (keyCode == KeyEvent.KEYCODE_DEL)
                    keyDel = 1;
                return false;
            }
        });

        if (keyDel == 0) {
            int len = txt_HomeNo.getText().length();
            if(len == 3) {
                txt_HomeNo.setText(txt_HomeNo.getText() + "-");
                txt_HomeNo.setSelection(txt_HomeNo.getText().length());
            }
        } else {
            keyDel = 0;
        }
    }

    @Override
    public void afterTextChanged(Editable arg0) {
        // TODO Auto-generated method stub
    }

    @Override
    public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
        // TODO Auto-generated method stub
    }
});
neo108
  • 5,156
  • 3
  • 27
  • 41
  • 1
    nice! I was able to get this working so that if you typed 6 digits in a zip code, it would insert the missing hyphen. – Phil Oct 28 '13 at 15:50
  • I'm trying to implement this code in my app, but I'm getting a `Cannot Resolve Symbol 'keyDel'` error in my code. I don't see where that variable is declared in the code snipet above. Any help on this? – Kevin Bright Aug 16 '16 at 00:34
  • I figured out my problem. You need to declare a variable `int keyDel` in the `addTextChangedListener` method. Now it's working although if you add two hyphens and backspace through both, the hyphens don't get added back properly. For example, I changed `if(len == 3)` to `if(len == 2 || len == 6)`, to add a hyphen after the 2nd and 6th digits. That works fine and even backspace works fine if you only delete one hyphen. If you delete both hyphens though and start typing again, the new text doesn't add the hyphens correctly. If you delete the whole editText field, the hyphens do work though – Kevin Bright Sep 02 '16 at 01:31
  • Thank you so much for adding dash but i have to remove also on backspace...please help me for this..... – Bali Dec 05 '16 at 13:09
  • but diffrent devices KeyEvent.KEYCODE_DEL is not support. for example my samsung device it is working but asus is not working.. – Ramesh Bhati Oct 06 '17 at 11:24
5

I have a few small changes to the solution of neo108 so it can work with both soft keyboard and hard keyboard, in my code for example the edittext will follow the rule to automatically add " " at position 5 and 9.

txtPhone.addTextChangedListener(new TextWatcher() {

        int keyDel;

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

        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            txtPhone.setOnKeyListener(new View.OnKeyListener() {
                @Override
                public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
                    if (keyCode == KeyEvent.KEYCODE_DEL) {
                        keyDel = 1;
                    }
                    return false;
                }
            });

            String currentString = txtPhone.getText().toString();
            int currentLength = txtPhone.getText().length();

            if (currentLength == 5 || currentLength == 9) {
                keyDel = 1;
            }

            if (keyDel == 0) {
                if (currentLength == 4 || currentLength == 8) {
                    txtPhone.setText(txtPhone.getText() + " ");
                    txtPhone.setSelection(txtPhone.getText().length());
                }
            } else {
                if (currentLength != 5 && currentLength != 9) {
                    keyDel = 0;
                } else if ((currentLength == 5 || currentLength == 9)
                        && !" ".equals(currentString.substring(currentLength - 1, currentLength))) {
                    txtPhone.setText(currentString.substring(0, currentLength - 1) + " "
                            + currentString.substring(currentLength - 1, currentLength));
                    txtPhone.setSelection(txtPhone.getText().length());
                }
            }
        }
4

I implemented a custom TextWatcher; this handles 10 and 11 digit phone numbers (i.e. 1-555-867-5309 and 555-867-5309). Allows adds, deletions, inserts, mass removal while maintaining proper cursor position.

    public class CustomPhoneTextWatcher implements TextWatcher {

    private final EditText editText;
    private String previousString;

    public CustomPhoneTextWatcher(EditText editText) {
        this.editText = editText;
    }

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

    }

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

    }

    @Override
    public void afterTextChanged(Editable editable) {
        // if the previous editable ends with a dash and new is shorter than previous
        // additionally remove preceding character
        if (previousString != null && previousString.endsWith("-") && editable.toString().length() < previousString.length()) {
            previousString = editable.toString();
            String removedCharacterPriorToDash = editable.toString().substring(0, editable.length() - 1);
            editText.setText(removedCharacterPriorToDash);
            int position = editText.length();
            Editable etext = editText.getText();
            Selection.setSelection(etext, position);
        } else {
            previousString = editable.toString();
            String numericString = StringUtils.removeNonnumeric(editable.toString());
            int stringLength = numericString.length();
            boolean startsWithOne = numericString.startsWith("1");
            numericString = numericString.substring(0, Math.min(stringLength, 10 + (startsWithOne ? 1 : 0)));

            int lastHyphenIndex = 6 + (startsWithOne ? 1 : 0);
            int secondToLastHyphenIndex = 3 + (startsWithOne ? 1 : 0);

            if (stringLength >= lastHyphenIndex) {
                numericString = numericString.substring(0, lastHyphenIndex) + "-" + numericString.substring(lastHyphenIndex, numericString.length());
            }
            if (stringLength >= secondToLastHyphenIndex) {
                numericString = numericString.substring(0, secondToLastHyphenIndex) + "-" + numericString.substring(secondToLastHyphenIndex, numericString.length());
            }
            if (numericString.startsWith("1")) {
                numericString = numericString.substring(0, 1) + "-" + numericString.substring(1, numericString.length());
            }
            if (!numericString.equals(editable.toString())) {
                editText.setText(numericString);
                int position = editText.length();
                Editable etext = editText.getText();
                Selection.setSelection(etext, position);
            }
        }
    }
}

StringUtils.removeNonnumeric(editable.toString()) is a call to this method:

   public static String removeNonnumeric(String text) {
        return text.replaceAll("[^\\d]", "");
    }
Tom Howard
  • 4,672
  • 2
  • 43
  • 48
  • This one has a couple issues: 1) If you select '-' on the keyboard, it deletes the text. When you get to the empty string case, it crashes 2) If you hold down delete, the delete gets interrupted. I added an implementation that I used some of your code from below that resolved these issues I ran into. – Ryan Newsom Jun 14 '18 at 19:32
1

Thanks for the all above answer.

  • The editText.setOnKeyListener() will never invoke when your device has only soft keyboard.
  • If we strictly follow the rule to add "-", then this code not always show desire result.

    editText.addTextChangedListener(new PhoneNumberFormattingTextWatcher());

but above code is best solution for formatting phone no.

Apart from above this solution, I write a code which work on all types of condition::

phoneNumber.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

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

        @Override
        public void afterTextChanged(Editable s) {
            if (len > phoneNumber.getText().length() ){
                len--;
                return;
            }
            len = phoneNumber.getText().length();

            if (len == 4 || len== 8) {
                String number = phoneNumber.getText().toString();
                String dash = number.charAt(number.length() - 1) == '-' ? "" : "-";
                number = number.substring(0, (len - 1)) + dash + number.substring((len - 1), number.length());
                phoneNumber.setText(number);
                phoneNumber.setSelection(number.length());
            }
        }
    });

this line of code required to add "-" on 3rd & 6th position of number. if (len == 4 || len== 8)

Raja
  • 36
  • 3
0

Do it yourself by using OnEditTextChangedListener and insert dash by counting number of chars, Counting Chars in EditText Changed Listener

Community
  • 1
  • 1
Hesam
  • 52,260
  • 74
  • 224
  • 365
0
import android.text.Editable;
import android.text.Selection;
import android.text.TextWatcher;
import android.util.Log;
import android.widget.EditText;

/**
 * Auto-formats a number using -.
 * Ex. 303-333-3333
 * Ex. 1-303-333-3333
 * Doesn't allow deletion of just -
 */
public class PhoneNumberFormattingTextWatcher implements TextWatcher {
    private static final String TAG = "PhoneNumberTextWatcher";

    private final EditText editText;
    private String previousNumber;

    /**
     * Indicates the change was caused by ourselves.
     */
    private boolean mSelfChange = false;

    public PhoneNumberFormattingTextWatcher(EditText editText) {
        this.editText = editText;
    }

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

    }

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

    }

    @Override
    public void afterTextChanged(Editable editable) {
        // if the previous editable ends with a dash and new is shorter than previous
        // additionally remove preceding character
        Log.i(TAG, "Previous String: " + previousNumber);

        //if self change ignore
        if (mSelfChange) {
            Log.i(TAG, "Ignoring self change");
            mSelfChange = false;
            return;
        }

        String phoneNumber = removeNonnumeric(editable.toString());
        int stringLength = phoneNumber.length();

        //empty case
        if(stringLength == 0) {
            mSelfChange = true;
            editText.setText("");
            return;
        }

        boolean startsWithOne = phoneNumber.charAt(0) == '1';
        int maxLength = 10 + (startsWithOne ? 1 : 0);

        //too large
        if(stringLength > maxLength) {
            Log.i(TAG, "String length is greater than max allowed, using previous string: " + previousNumber);
            mSelfChange = true;
            editText.setText(previousNumber);
            Editable etext = editText.getText();
            Selection.setSelection(etext, previousNumber.length());
            return;
        }

        phoneNumber = formatPhoneNumber(phoneNumber);

        if(previousNumber != null && phoneNumber.length() == previousNumber.length()) {
            //user deleting last character, and it is a -
            if(phoneNumber.endsWith("-")) {
                phoneNumber = phoneNumber.substring(0, phoneNumber.length()-2);
            }
        }

        mSelfChange = true;
        previousNumber = phoneNumber;
        editText.setText(phoneNumber);
        Editable etext = editText.getText();
        Selection.setSelection(etext, phoneNumber.length());
    }

    private String formatPhoneNumber(String phoneNumber) {
        int stringLength = phoneNumber.length();
        //check if starts with 1, if it does, dash index is increased by 1
        boolean startsWithOne = phoneNumber.charAt(0) == '1';

        //if the length of the string is 6, add another dash
        int lastHyphenIndex = 6 + (startsWithOne ? 1 : 0);
        if (stringLength >= lastHyphenIndex) {
            phoneNumber = phoneNumber.substring(0, lastHyphenIndex) + "-" + phoneNumber.substring(lastHyphenIndex, phoneNumber.length());
        }
        //if the length of the string is 3, add a dash
        int secondToLastHyphenIndex = 3 + (startsWithOne ? 1 : 0);
        if (stringLength >= secondToLastHyphenIndex) {
            phoneNumber = phoneNumber.substring(0, secondToLastHyphenIndex) + "-" + phoneNumber.substring(secondToLastHyphenIndex, phoneNumber.length());
        }
        //If the number starts with 1, add a dash after 1
        if (phoneNumber.startsWith("1")) {
            phoneNumber = phoneNumber.substring(0, 1) + "-" + phoneNumber.substring(1, phoneNumber.length());
        }

        return phoneNumber;
    }

    private static String removeNonnumeric(String text) {
        return text.replaceAll("[^\\d]", "");
    }
}
Ryan Newsom
  • 696
  • 7
  • 12