9

Is it possible to auto insert characters into an EditText as the user inputs data?

I.e. if the user is entering a long number such as 123456789012, is it possible for this number to appear as he is typing it in the edit text box, but with a dash every 4th character?

So as you type the number above you would see it being entered in the EditText box but would look like this: 1234-5678-9012.

Currently I have an app where you can enter a long number and then press a button and it inserts the dashes for you, but I'm curious if it could be done as you type?

Many thanks for any help.

fernandohur
  • 7,014
  • 11
  • 48
  • 86
Entropy1024
  • 7,847
  • 9
  • 30
  • 32

6 Answers6

15

By tagging android, I think you are discussing about android editText, is so you can do it by listening the TextChangedListener,

EDITED: for backspace

editText.addTextChangedListener(new TextWatcher() {
            int len=0;
            @Override
            public void afterTextChanged(Editable s) { 
                String str = editText.getText().toString(); 
                 if(str.length()==4&& len <str.length()){//len check for backspace 
                    editText.append("-");
                }
            }

            @Override
            public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {

             String str = editText.getText().toString(); 
              len = str.length();
            }

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


        }); 
Labeeb Panampullan
  • 34,521
  • 28
  • 94
  • 112
7

to solve this issue, i write a class "AutoAddTextWatcher" :

1. Auto insert text into EditText.
2. insert text into EditText at positions you are setted.
3. delete text in EditText at positions you are setted, when text length bigger than 1.

enter image description here

code snippet :

mEditText_birthday.addTextChangedListener(new AutoAddTextWatcher(mEditText_birthday,
            "/",
            new TextWatcher() {},
            4, 6));

AutoAddTextWatcher class

import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;


/**
 * Created by henry.chuang on 2016/5/12.
 */
public class AutoAddTextWatcher implements TextWatcher {
    private CharSequence mBeforeTextChanged;
    private TextWatcher mTextWatcher;
    private int[] mArray_pos;
    private EditText mEditText;
    private String mAppentText;

    public AutoAddTextWatcher(EditText editText, String appendText, int... position){
        this.mEditText = editText;
        this.mAppentText = appendText;
        this.mArray_pos = position.clone();
    }
    public AutoAddTextWatcher(EditText editText, String appendText, TextWatcher textWatcher, int... position){
        this(editText, appendText, position);
        this.mTextWatcher = textWatcher;
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        mBeforeTextChanged = s.toString();

        if(mTextWatcher != null)
            mTextWatcher.beforeTextChanged(s, start, count, after);

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        for (int i = 0; i < mArray_pos.length; i++) {
            if(((mBeforeTextChanged.length() - mAppentText.length() * i) == (mArray_pos[i] - 1) &&
                    (s.length() - mAppentText.length() * i) == mArray_pos[i])){
                mEditText.append(mAppentText);

                break;
            }

            if(((mBeforeTextChanged.length() - mAppentText.length() * i) == mArray_pos[i] &&
                    (s.length() - mAppentText.length() * i) == (mArray_pos[i] + 1))){
                int idx_start = mArray_pos[i] + mAppentText.length() * i;
                int idx_end = Math.min(idx_start + mAppentText.length(), s.length());

                String sub = mEditText.getText().toString().substring(idx_start,  idx_end);

                if(!sub.equals(mAppentText)){
                    mEditText.getText().insert(s.length() - 1, mAppentText);
                }

                break;
            }

            if(mAppentText.length() > 1 &&
                    (mBeforeTextChanged.length() - mAppentText.length() * i) == (mArray_pos[i] + mAppentText.length()) &&
                    (s.length() - mAppentText.length() * i) == (mArray_pos[i] + mAppentText.length() - 1)){
                int idx_start = mArray_pos[i] + mAppentText.length() * i;
                int idx_end = Math.min(idx_start + mAppentText.length(), s.length());

                mEditText.getText().delete(idx_start, idx_end);

                break;
            }

        }

        if(mTextWatcher != null)
            mTextWatcher.onTextChanged(s, start, before, count);

    }

    @Override
    public void afterTextChanged(Editable s) {
        if(mTextWatcher != null)
            mTextWatcher.afterTextChanged(s);

    }

}

complete demo source :
https://github.com/henrychuangtw/AutoInsertEditText

HenryChuang
  • 1,449
  • 17
  • 28
  • Wow dude! You are a genius! Thank you so much for this... I have tried SO MANY solutions, but nothing worked right. I needed to get it formatted like this: 12-345-67. Every other solution always had weird things happen when you deleted and then tried to re-enter. Your solutions works PERFECTLY! One thing to note though, for your class to work properly, you need to set the input type in the XML file to `android:inputType="phone"` I tried initially with `android:inputType="number"` and it didn't work. I checked your github page and saw you used `phone`, and that now works. Great job! – Kevin Bright Oct 26 '16 at 01:11
  • Here's my implementation: `enterUserID.addTextChangedListener(new AutoAddTextWatcher(enterUserID, "-", 2, 5));` – Kevin Bright Oct 26 '16 at 01:20
  • @KevinBright Thanks your encouragement and suggestion, I will try it. – HenryChuang Oct 26 '16 at 01:31
  • No, thank you! I can't believe how hard this is to do properly in Android! – Kevin Bright Oct 26 '16 at 01:35
  • @HenryChuang: your code was super. previously I implemented my own way by struggling a lot. But your code will help people definitely. If I want to implement copy paste listener to your code, how can we achieve that. – shyam.y May 01 '17 at 05:08
  • @sham.y copy paste listener? copy all text on edittext? – HenryChuang May 01 '17 at 07:07
  • @HenryChuang : yes, if user copied text and pasted in edit text. – shyam.y May 02 '17 at 00:16
  • Hi,Im using this class,But one issue we are observed is when user bring the cursor to back of the string then the position of delimiter is missing as per the requirement.Can you please suggest me is there any solution for this. – Sai Durga Nov 07 '17 at 12:49
0
@Override
public void afterTextChanged(Editable s) {

    if(s.length() == 3 && len < s.length()){
        s.append(" - ");
    }

}

@Override
public void beforeTextChanged(CharSequence s, int start, int count,
        int after) {
    len = s.length();
}

This will do as well, only this code will insert " - " after 3rd character.

Himanshu
  • 31,810
  • 31
  • 111
  • 133
0

This is what I used

private boolean mInEdit;

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
    if (!mInEdit) {
        mInEdit = true;
        String delimiter = " - ";
        //Remove chars from your delimiter first
        String digits = s.toString().replaceAll("[- ]", "")
                .replaceAll("\\d{4}", "$0" + delimiter);
        //Handle deletion
        int dLength = delimiter.length();
        if (before > count && digits.endsWith(delimiter.charAt(dLength - 1)) {
            digits = digits.substring(0, digits.length() - dLength);
        }
        mCardNumber.setText(digits);
        mCardNumber.setSelection(mCardNumber.length());
        mInEdit = false;
    }
}

Here you replace delimiter with what you want to separate digits.

Yaroslav
  • 4,750
  • 3
  • 22
  • 33
0

For those still facing trouble with backspace and multiple hyphens -

new TextWatcher() 
{
        boolean hyphenExists;

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            if (s.length() >= 6 && s.charAt(5) == '-') {
                hyphenExists = true;
            } else {
                hyphenExists = false;
            }

            Log.d("TAG", "beforeTextChanged " + s.toString());
        }

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

            Log.d("TAG", "onTextChanged " + s.toString());
        }

        @Override
        public void afterTextChanged(Editable s) {
            if (s.length() == 5) {
                if (!hyphenExists)
                    s.append('-');
            }
            Log.d("TAG", "afterTextChanged " + s.toString());
        }
    }
Taranmeet Singh
  • 1,199
  • 1
  • 11
  • 14
0

You can achieve this with on text changed

in my case, i have to format input like this : xxx xxx-xxxx

i done as given below:

etMobileNumber.addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(s: Editable?) {


        }

        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
        }

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            if (etMobileNumber.text.length == 3 && count != 0) {
                val text = etMobileNumber.getText().toString() + " "
                etMobileNumber.setText(text)
                etMobileNumber.setSelection(text.length)
            } else if (etMobileNumber.text.length == 7 && count != 0) {
                val text = etMobileNumber.getText().toString() + "-"
                etMobileNumber.setText(text)
                etMobileNumber.setSelection(text.length)
            }
        }
    })

and the result is very dynamic on the go while typing.

input- 1234567890 result - 123 456-7890

amit bansode
  • 339
  • 3
  • 14