android EditText,键盘textWatcher问题

发布于 2024-10-31 15:38:18 字数 6550 浏览 1 评论 0原文

我正在开发一个 Android 应用程序,我有一个 EditText,用户可以在其中输入数字。我想使用不同的货币格式(例如##,##,###)来格式化数字,并且我想即时执行此操作,即当用户输入每个数字时(而不是按下回车键时)。我用谷歌搜索了一下,发现了 TextWatcher 我第一次发现它很有前途,但是事实证明这是一种绝对的痛苦。我正在 HTC Desire 手机上调试我的代码,该手机只有软键盘。

现在我想在用户按下数字(0到9)、del(退格)键和回车键时得到回调。通过我的测试,我发现了这些(至少在我的手机上)

1) editText onKeyListener 被调用 当用户按 del 或 Enter 键时。 当用户按下回车键时,onKey 一次输入调用函数两次 (我相信这是针对 ACTION_UP 和 行动_向下)。当用户按下del时, onKey 被调用一次(仅适用于 ACTION_DOWN)我不知道为什么。 当用户使用 onKey 时,永远不会调用 onKey 按任意数字(0 到 9),我也是 听不懂。

2) TextWatchers 3个回调函数 被称为(beforeTextChanged, onTextChanged、afterTextChanged) 每当用户按下任意数字(0 到 9) 键。所以我想通过使用 TextWatcher 和 onKeyListener 结合在一起 我可以获得我需要的所有回调。

现在我的问题是这些..

1) 首先在我的 HTC 软键盘中 是一个键(带有 向下箭头),当我点击它时 键盘辞职不给 任何回调。我还是不敢相信 android 让用户编辑字段 并辞职而不让计划 处理(保存)编辑。现在我的 editText 显示一个值,我的 对象有另一个值(我正在保存 用户在输入时进行编辑并处理回来 按键盘重置 editText 值与中的值 反对,但我对此没有答案 键盘向下键)。

2)其次,我要格式化数字 用户输入新数字后。说 我在 editText 上已经有 123 了 用户输入按下 4,我想要我的 editText 显示 1,234。我吃饱了 onTextChanged() 上的数字和 afterTextChanged() 我可以格式化 号码并将其放回 在这些回调中的任何一个中编辑文本。 我应该使用哪一个?哪个是 最佳实践?

3)第三个是最关键的 问题。当应用程序启动时,我把 editText 中的当前对象值。 假设我在 onResume() 上输入了 123,当 用户输入一个数字(比如 4)我想要它 是 1234。但是在我的 onTextChanged 上 我得到的回调是 4123。 我再按一个键(比如 5)我是 得到 45123。所以对于用户输入 editText 光标指向末尾 文本。但是当值设置为 手,editText光标似乎不是 更新。我相信我必须做 textWatcher 回调中的某些内容但是 我不知道我应该做什么。

我在下面发布我的代码。

public class AppHome extends AppBaseActivity {
    private EditText ed = null;
    private NumberFormat amountFormatter = null;
    private boolean  isUserInput = true;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.app_home_screen);

        ed = (EditText)findViewById(R.id.main_amount_textfield);
        amountFormatter = new DecimalFormat("##,##,###");


        ed.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if(event.getAction() == KeyEvent.ACTION_DOWN) 
                    return true;
                String strippedAmount = ed.getText().toString().replace(",", "");
                if(keyCode == KeyEvent.KEYCODE_DEL){
                    //delete pressed, strip number of comas and then delete least significant digit.
                    strippedAmount = strippedAmount.substring(0, strippedAmount.length() - 1);
                    int amountNumeral = 0;
                    try{
                        amountNumeral = Integer.parseInt(strippedAmount);
                    } catch(NumberFormatException e){
                    }
                    myObject.amount = amountNumeral;
                    isUserInput = false;
                    setFormattedAmount(amountNumeral,ed.getId());
                }else if(keyCode == KeyEvent.KEYCODE_ENTER){
                    //enter pressed, save edits and resign keyboard
                    int amountNumeral = 0;
                    try{
                        amountNumeral = Integer.parseInt(strippedAmount);
                    } catch(NumberFormatException e){
                    }
                    myObject.amount = amountNumeral;
                    isUserInput = false;
                    setFormattedAmount(myObject.amount,ed.getId());
                    //save edits
                    save();
                    //resign keyboard..
                    InputMethodManager in = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    in.hideSoftInputFromWindow(AppHome.this.getCurrentFocus().getWindowToken(),InputMethodManager.HIDE_NOT_ALWAYS);
                }
                return true;
            }
        });

        TextWatcher inputTextWatcher = new TextWatcher() {
            public void afterTextChanged(Editable s) { 
                if(isUserInput == false){
                    //textWatcher is recursive. When editText value is changed from code textWatcher callback gets called. So this variable acts as a flag which tells whether change is user generated or not..Possibly buggy code..:(
                    isUserInput = true;
                    return;
                }
                String strippedAmount = ed.getText().toString().replace(",", "");
                int amountNumeral = 0;
                try{
                    amountNumeral = Integer.parseInt(strippedAmount);
                } catch(NumberFormatException e){
                }
                isUserInput = false;
                setFormattedAmount(amountNumeral,ed.getId());
            }

            public void beforeTextChanged(CharSequence s, int start, int count, int after){
            }
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }
        };

        ed.addTextChangedListener(inputTextWatcher);
    }//end of onCreate...

    public void setFormattedAmount(Integer amount, Integer inputBoxId){
        double amountValue = 0;
        String textString =null;
        TextView amountInputBox = (TextView) findViewById(inputBoxId);

        amountValue = Double.parseDouble(Integer.toString(amount));
        textString = amountFormatter.format(amountValue).toString();
        amountInputBox.setText(textString);
    }
}

我知道这是一个大问题,但我花了两天的时间来解决同样的问题。我是 Android 新手,仍然不敢相信没有简单的方法可以动态处理文本编辑数据(我在 iphone 上轻松完成了同样的操作)。谢谢大家

编辑:使用输入过滤器后

InputFilter filter = new InputFilter() { 
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { 
            String strippedAmount = dest.toString() + source;
            strippedAmount = strippedAmount.replace(",", "");

        int amountNumeral = 0;
        try{
            amountNumeral = Integer.parseInt(strippedAmount);
        } catch(NumberFormatException e){
        }           
            return amountFormatter.format(amountNumeral).toString(); 
    } 
}; 

ed.setFilters(new InputFilter[]{filter}); 

当应用程序启动时,我在 editText 上输入 1,234

myObject.amount = 1234;
ed.setText(amountFormatter.format(myObject.amount).toString());

然后,当用户单击 editText 时,键盘会弹出,并说用户输入数字 6

我得到:61234 我想要: 12346

I am working on a android app and I have an EditText where user can input numbers. I want to format the number using different currency formats (say ##,##,###) and I want to do it on the fly, ie when user enter each digit(not when enter is pressed). I googled around, and came across TextWatcher which I first found promising, but it turned out to be an absolute pain. I am debugging my code on a HTC Desire phone which only has a soft keyboard.

Now I want to get a callback when user press numbers (0 to 9) , del (backspace) key and enter key. From my testing I found these (atleast on my phone)

1) editText onKeyListener is called
when user presses del or enter key.
When user presses enter, onKey
function is called twice for one enter
(which I believe is for ACTION_UP and
ACTION_DOWN). When user presses del,
onKey is called once (only for
ACTION_DOWN) which I dont know why.
onKey is never called when user
presses any digits(0 to 9) which too I
cant understand.

2) TextWatchers 3 callback functions
are called (beforeTextChanged,
onTextChanged, afterTextChanged)
whenever user presses any number (0 to
9) key . So I thought by using
TextWatcher and onKeyListener together
I can get all callbacks I need.

Now my questions are these..

1) First in my HTC soft keyboard there
is a key (a keyboard symbol with a
down arrow) and when I click on it
keyboard is resigned without giving
any callback. I still cant believe
android letting user to edit a field
and resign without letting program to
process (save) the edit. Now my
editText is showing one value and my
object has another value (I am saving
user edits on enter, and handling back
press on keyboard by reseting
editText value with the value in the
object , but I have no answer to this
keyboard down key).

2) Second, I want to format the number
after user entered the new digit. Say
I already have 123 on editText and
user entered pressed 4, I want my
editText to display 1,234. I get full
number on onTextChanged() and
afterTextChanged() and I can format
the number and put it back to
editText in any of these callback.
Which one should I use? Which is the
best practice?

3) Third one is the most crucial
problem. When app start I put the
current object value in the editText.
Say I put 123 on onResume(), and when
user enter a digit (say 4) I want it
to be 1234. But on my onTextChanged
callback what I am getting is 4123. When
I press one more key (say 5) I am
getting 45123. So for user inputs
editText cursor are pointing to end of
the text. But when value is set by
hand, editText cursor dont seems to be
updating. I believe I have to do
something in textWatcher callbacks but
I dont know what I should do.

I am posting my code below.

public class AppHome extends AppBaseActivity {
    private EditText ed = null;
    private NumberFormat amountFormatter = null;
    private boolean  isUserInput = true;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.app_home_screen);

        ed = (EditText)findViewById(R.id.main_amount_textfield);
        amountFormatter = new DecimalFormat("##,##,###");


        ed.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if(event.getAction() == KeyEvent.ACTION_DOWN) 
                    return true;
                String strippedAmount = ed.getText().toString().replace(",", "");
                if(keyCode == KeyEvent.KEYCODE_DEL){
                    //delete pressed, strip number of comas and then delete least significant digit.
                    strippedAmount = strippedAmount.substring(0, strippedAmount.length() - 1);
                    int amountNumeral = 0;
                    try{
                        amountNumeral = Integer.parseInt(strippedAmount);
                    } catch(NumberFormatException e){
                    }
                    myObject.amount = amountNumeral;
                    isUserInput = false;
                    setFormattedAmount(amountNumeral,ed.getId());
                }else if(keyCode == KeyEvent.KEYCODE_ENTER){
                    //enter pressed, save edits and resign keyboard
                    int amountNumeral = 0;
                    try{
                        amountNumeral = Integer.parseInt(strippedAmount);
                    } catch(NumberFormatException e){
                    }
                    myObject.amount = amountNumeral;
                    isUserInput = false;
                    setFormattedAmount(myObject.amount,ed.getId());
                    //save edits
                    save();
                    //resign keyboard..
                    InputMethodManager in = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    in.hideSoftInputFromWindow(AppHome.this.getCurrentFocus().getWindowToken(),InputMethodManager.HIDE_NOT_ALWAYS);
                }
                return true;
            }
        });

        TextWatcher inputTextWatcher = new TextWatcher() {
            public void afterTextChanged(Editable s) { 
                if(isUserInput == false){
                    //textWatcher is recursive. When editText value is changed from code textWatcher callback gets called. So this variable acts as a flag which tells whether change is user generated or not..Possibly buggy code..:(
                    isUserInput = true;
                    return;
                }
                String strippedAmount = ed.getText().toString().replace(",", "");
                int amountNumeral = 0;
                try{
                    amountNumeral = Integer.parseInt(strippedAmount);
                } catch(NumberFormatException e){
                }
                isUserInput = false;
                setFormattedAmount(amountNumeral,ed.getId());
            }

            public void beforeTextChanged(CharSequence s, int start, int count, int after){
            }
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }
        };

        ed.addTextChangedListener(inputTextWatcher);
    }//end of onCreate...

    public void setFormattedAmount(Integer amount, Integer inputBoxId){
        double amountValue = 0;
        String textString =null;
        TextView amountInputBox = (TextView) findViewById(inputBoxId);

        amountValue = Double.parseDouble(Integer.toString(amount));
        textString = amountFormatter.format(amountValue).toString();
        amountInputBox.setText(textString);
    }
}

I know it is a big question, but I am working on this same problem for 2 days. I am new to android and still cant believe that there is no easy way to process textEdit data on the fly (I done the same on iphone with ease). Thanks all

EDIT: after using input filter

InputFilter filter = new InputFilter() { 
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { 
            String strippedAmount = dest.toString() + source;
            strippedAmount = strippedAmount.replace(",", "");

        int amountNumeral = 0;
        try{
            amountNumeral = Integer.parseInt(strippedAmount);
        } catch(NumberFormatException e){
        }           
            return amountFormatter.format(amountNumeral).toString(); 
    } 
}; 

ed.setFilters(new InputFilter[]{filter}); 

When app starts I am putting 1,234 on the editText

myObject.amount = 1234;
ed.setText(amountFormatter.format(myObject.amount).toString());

Then when user clicks the editText, keyboard pops up, and say user enters digit 6

I am getting : 61234 I want :
12346

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

笑脸一如从前 2024-11-07 15:38:18

好吧,经过一番努力后,我找到了解决光标位置问题的方法。我不知道这是否是正确的方法,但我得到了它的工作。

    TextWatcher inputTextWatcher = new TextWatcher() {
        public void afterTextChanged(Editable s) { 
            if(isUserInput == false){
                //textWatcher is recursive. When editText value is changed from code textWatcher callback gets called. So this variable acts as a flag which tells whether change is user generated or not..Possibly buggy code..:(
                isUserInput = true;
                ed.setSelection(ed.getText().length());
                return;
            }
            String strippedAmount = ed.getText().toString().replace(",", "");
            int amountNumeral = 0;
            try{
                amountNumeral = Integer.parseInt(strippedAmount);
            } catch(NumberFormatException e){
            }
            isUserInput = false;
            setFormattedAmount(amountNumeral,ed.getId());
        }

        public void beforeTextChanged(CharSequence s, int start, int count, int after){
        }
        public void onTextChanged(CharSequence s, int start, int before, int count) {
        }
    };
ed.addTextChangedListener(inputTextWatcher);


ed.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int length          =   ed.getText().length();
            ed.setCursorVisible(true);
            ed.setSelection(length);
        }
    });

ed.setOnKeyListener(new View.OnKeyListener() {
    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
            if(event.getAction() == KeyEvent.ACTION_UP) 
                return true;
            String strippedAmount = ed.getText().toString().replace(",", "");
            if(keyCode == KeyEvent.KEYCODE_DEL){
                //delete pressed, strip number of comas and then delete least significant digit.
                strippedAmount = strippedAmount.substring(0, strippedAmount.length() - 1);
                int amountNumeral = 0;
                try{
                    amountNumeral = Integer.parseInt(strippedAmount);
                } catch(NumberFormatException e){
                }
                isUserInput = false;
                setFormattedAmount(amountNumeral,ed.getId());
                return true;
            }else if(keyCode == KeyEvent.KEYCODE_ENTER){
                //enter pressed, save edits and resign keyboard
                int amountNumeral = 0;
                try{
                    amountNumeral = Integer.parseInt(strippedAmount);
                } catch(NumberFormatException e){
                }
                isUserInput = false;
                setFormattedAmount(amountNumeral,ed.getId());
                //save edits
                //resign keyboard..
                InputMethodManager in = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                in.hideSoftInputFromWindow(AppHome.this.getCurrentFocus().getWindowToken(),InputMethodManager.HIDE_NOT_ALWAYS);
                return true;
            }
            return false;
    }
});

我所做的是在 editText 的 onClick() 上,我强行将光标位于当前 EditText 文本的末尾,当用户按下任何数字时我也做了同样的事情。希望它能帮助别人。感谢所有试图提供帮助的人。

Well, after much head banging, I found a work around for cursor position problem..I dont know whether it is the correct way, But I got it working..

    TextWatcher inputTextWatcher = new TextWatcher() {
        public void afterTextChanged(Editable s) { 
            if(isUserInput == false){
                //textWatcher is recursive. When editText value is changed from code textWatcher callback gets called. So this variable acts as a flag which tells whether change is user generated or not..Possibly buggy code..:(
                isUserInput = true;
                ed.setSelection(ed.getText().length());
                return;
            }
            String strippedAmount = ed.getText().toString().replace(",", "");
            int amountNumeral = 0;
            try{
                amountNumeral = Integer.parseInt(strippedAmount);
            } catch(NumberFormatException e){
            }
            isUserInput = false;
            setFormattedAmount(amountNumeral,ed.getId());
        }

        public void beforeTextChanged(CharSequence s, int start, int count, int after){
        }
        public void onTextChanged(CharSequence s, int start, int before, int count) {
        }
    };
ed.addTextChangedListener(inputTextWatcher);


ed.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int length          =   ed.getText().length();
            ed.setCursorVisible(true);
            ed.setSelection(length);
        }
    });

ed.setOnKeyListener(new View.OnKeyListener() {
    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
            if(event.getAction() == KeyEvent.ACTION_UP) 
                return true;
            String strippedAmount = ed.getText().toString().replace(",", "");
            if(keyCode == KeyEvent.KEYCODE_DEL){
                //delete pressed, strip number of comas and then delete least significant digit.
                strippedAmount = strippedAmount.substring(0, strippedAmount.length() - 1);
                int amountNumeral = 0;
                try{
                    amountNumeral = Integer.parseInt(strippedAmount);
                } catch(NumberFormatException e){
                }
                isUserInput = false;
                setFormattedAmount(amountNumeral,ed.getId());
                return true;
            }else if(keyCode == KeyEvent.KEYCODE_ENTER){
                //enter pressed, save edits and resign keyboard
                int amountNumeral = 0;
                try{
                    amountNumeral = Integer.parseInt(strippedAmount);
                } catch(NumberFormatException e){
                }
                isUserInput = false;
                setFormattedAmount(amountNumeral,ed.getId());
                //save edits
                //resign keyboard..
                InputMethodManager in = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                in.hideSoftInputFromWindow(AppHome.this.getCurrentFocus().getWindowToken(),InputMethodManager.HIDE_NOT_ALWAYS);
                return true;
            }
            return false;
    }
});

What I have done is on onClick() of editText, I forcefully put the cursor at the end of the current EditText text, and I have done the same when user pressed any digit. Hope it helps someone..Thanks for everyone who tried to help.

ま柒月 2024-11-07 15:38:18

对于屏蔽输入,您可以子类 InputFilter

下面是一个示例 InputFilter 子类,全部小写字母大写:

   /**
     * This filter will capitalize all the lower case letters that are added
     * through edits.
     */
    public static class AllCaps implements InputFilter {
        public CharSequence filter(CharSequence source, int start, int end,
                                   Spanned dest, int dstart, int dend) {
            for (int i = start; i < end; i++) {
                if (Character.isLowerCase(source.charAt(i))) {
                    char[] v = new char[end - start];
                    TextUtils.getChars(source, start, end, v, 0);
                    String s = new String(v).toUpperCase();

                    if (source instanceof Spanned) {
                        SpannableString sp = new SpannableString(s);
                        TextUtils.copySpansFrom((Spanned) source,
                                                start, end, null, sp, 0);
                        return sp;
                    } else {
                        return s;
                    }
                }
            }

            return null; // keep original
        }
    }

上面的代码取自 Android对InputFilter的实现

For Masked input, you can subclass InputFilter

Below is a sample InputFilter subclass, which capitalizes all lower case letters:

   /**
     * This filter will capitalize all the lower case letters that are added
     * through edits.
     */
    public static class AllCaps implements InputFilter {
        public CharSequence filter(CharSequence source, int start, int end,
                                   Spanned dest, int dstart, int dend) {
            for (int i = start; i < end; i++) {
                if (Character.isLowerCase(source.charAt(i))) {
                    char[] v = new char[end - start];
                    TextUtils.getChars(source, start, end, v, 0);
                    String s = new String(v).toUpperCase();

                    if (source instanceof Spanned) {
                        SpannableString sp = new SpannableString(s);
                        TextUtils.copySpansFrom((Spanned) source,
                                                start, end, null, sp, 0);
                        return sp;
                    } else {
                        return s;
                    }
                }
            }

            return null; // keep original
        }
    }

The above code is taken from Android's implementation of InputFilter

微凉 2024-11-07 15:38:18

经过几个小时的工作,我制作了一个电话输入掩码。
例如,输入“123456”后,它会将其转换为“+1 (234) 56”。从任何位置删除任何符号后,光标会移动到正确的位置,而不是移动到开头或结尾。

活动中:

    etPhone.addTextChangedListener(new PhoneWatcher(etPhone));

课堂上:

private class PhoneWatcher implements TextWatcher {
    private static final String PHONE_MASK = "+# (###) ###-##-##";
    private final char[] PHONE_MASK_ARRAY = PHONE_MASK.toCharArray();

    private boolean isInTextChanged;
    private boolean isInAfterTextChanged;
    private EditText editText;
    private int shiftCursor;
    private String text;
    private int cursor;

    public PhoneWatcher(EditText editText) {
        super();
        this.editText = editText;
        isInTextChanged = false;
        isInAfterTextChanged = false;
    }

    @Override
    public synchronized void beforeTextChanged(CharSequence s, int start, int count, int after) {
        shiftCursor = after - count;
    }

    @Override
    public synchronized void onTextChanged(CharSequence s, int start, int before, int count) {
        if (!isInTextChanged) {
            isInTextChanged = true;

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < s.length(); i++) {
                char symbol = s.charAt(i);
                if (symbol >= '0' && symbol <= '9')
                    sb.append(symbol);
            }
            String digits = sb.toString();

            sb.setLength(0);
            int j = 0;
            for (int i = 0; i < digits.length(); i++) {
                char digit = digits.charAt(i);
                while (j < PHONE_MASK_ARRAY.length) {
                    if (PHONE_MASK_ARRAY[j] == '#') {
                        sb.append(digit);
                        j++;
                        break;
                    } else {
                        sb.append(PHONE_MASK_ARRAY[j]);
                        j++;
                    }
                }
            }

            cursor = editText.getSelectionStart();
            text = sb.toString();

            if (shiftCursor > 0) {
                if (cursor > text.length())
                    cursor = text.length();
                else {
                    while (cursor < PHONE_MASK_ARRAY.length && PHONE_MASK_ARRAY[cursor - 1] != '#') {
                        cursor++;
                    }
                }
            } else if (shiftCursor < 0) {
                while (cursor > 0 && PHONE_MASK_ARRAY[cursor - 1] != '#') {
                    cursor--;
                }
            }
        }
    }

    public synchronized void afterTextChanged(Editable s) {
        if (!isInAfterTextChanged) {
            isInAfterTextChanged = true;

            editText.setText(text);
            editText.setSelection(cursor);

            isInTextChanged = false;
            isInAfterTextChanged = false;
        }
    }
}

After several hours of working I made a phone input mask.
For istance, after entering "123456" it converts it to "+1 (234) 56". After deleting of any symbol from any position a cursor moves to a right position, not to a beginning or ending.

In Activity:

    etPhone.addTextChangedListener(new PhoneWatcher(etPhone));

In class:

private class PhoneWatcher implements TextWatcher {
    private static final String PHONE_MASK = "+# (###) ###-##-##";
    private final char[] PHONE_MASK_ARRAY = PHONE_MASK.toCharArray();

    private boolean isInTextChanged;
    private boolean isInAfterTextChanged;
    private EditText editText;
    private int shiftCursor;
    private String text;
    private int cursor;

    public PhoneWatcher(EditText editText) {
        super();
        this.editText = editText;
        isInTextChanged = false;
        isInAfterTextChanged = false;
    }

    @Override
    public synchronized void beforeTextChanged(CharSequence s, int start, int count, int after) {
        shiftCursor = after - count;
    }

    @Override
    public synchronized void onTextChanged(CharSequence s, int start, int before, int count) {
        if (!isInTextChanged) {
            isInTextChanged = true;

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < s.length(); i++) {
                char symbol = s.charAt(i);
                if (symbol >= '0' && symbol <= '9')
                    sb.append(symbol);
            }
            String digits = sb.toString();

            sb.setLength(0);
            int j = 0;
            for (int i = 0; i < digits.length(); i++) {
                char digit = digits.charAt(i);
                while (j < PHONE_MASK_ARRAY.length) {
                    if (PHONE_MASK_ARRAY[j] == '#') {
                        sb.append(digit);
                        j++;
                        break;
                    } else {
                        sb.append(PHONE_MASK_ARRAY[j]);
                        j++;
                    }
                }
            }

            cursor = editText.getSelectionStart();
            text = sb.toString();

            if (shiftCursor > 0) {
                if (cursor > text.length())
                    cursor = text.length();
                else {
                    while (cursor < PHONE_MASK_ARRAY.length && PHONE_MASK_ARRAY[cursor - 1] != '#') {
                        cursor++;
                    }
                }
            } else if (shiftCursor < 0) {
                while (cursor > 0 && PHONE_MASK_ARRAY[cursor - 1] != '#') {
                    cursor--;
                }
            }
        }
    }

    public synchronized void afterTextChanged(Editable s) {
        if (!isInAfterTextChanged) {
            isInAfterTextChanged = true;

            editText.setText(text);
            editText.setSelection(cursor);

            isInTextChanged = false;
            isInAfterTextChanged = false;
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文