android EditText ,keyboard textWatcher problem

偶尔善良 提交于 2019-11-30 03:42:28

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.

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

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;
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!