android EditText ,keyboard textWatcher problem

前端 未结 3 1384
情书的邮戳
情书的邮戳 2020-12-28 09:22

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

相关标签:
3条回答
  • 2020-12-28 10:05

    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.

    0 讨论(0)
  • 2020-12-28 10:09

    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;
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-28 10:18

    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

    0 讨论(0)
提交回复
热议问题