Custom format edit text input android to accept credit card number

后端 未结 8 711
终归单人心
终归单人心 2020-11-29 01:46

how to make edit text accept input in format

4digitnumber-4dignumber-4dignumber-4dignumber   

The code

text.addTextChangedL         


        
相关标签:
8条回答
  • 2020-11-29 02:48

    It seems to me the answers presented here do not work properly with delete, delete from the middle operations, etc. Here is my code. It doesn't restrict the length of input, but seems to be ok with various insertions and deletions:

    import android.text.Editable;
    import android.text.TextWatcher;
    import android.view.KeyEvent;
    import android.view.View;
    import android.widget.EditText;
    
    public class HyphenDelimitTextWatcher implements TextWatcher {
        EditText mEditText;
        boolean mInside = false;
        boolean mWannaDeleteHyphen = false;
        boolean mKeyListenerSet = false;
        final static String MARKER = "|"; // filtered in layout not to be in the string
    
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            if(!mKeyListenerSet) {
                mEditText.setOnKeyListener(new View.OnKeyListener() {
                    @Override
                    public boolean onKey(View v, int keyCode, KeyEvent event) {
                        try {
                            mWannaDeleteHyphen = (keyCode == KeyEvent.KEYCODE_DEL
                                    && mEditText.getSelectionEnd() - mEditText.getSelectionStart() <= 1
                                    && mEditText.getSelectionStart() > 0
                                    && mEditText.getText().toString().charAt(mEditText.getSelectionEnd() - 1) == '-');
                        } catch (IndexOutOfBoundsException e) {
                            // never to happen because of checks
                        }
                        return false;
                    }
                });
                mKeyListenerSet = true;
            }
        }
    
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            if (mInside) // to avoid recursive calls
                return;
            mInside = true;
    
            int currentPos = mEditText.getSelectionStart();
            String string = mEditText.getText().toString().toUpperCase();
            String newString = makePrettyString(string);
    
            mEditText.setText(newString);
            try {
                mEditText.setSelection(getCursorPos(string, newString, currentPos, mWannaDeleteHyphen));
            } catch (IndexOutOfBoundsException e) {
                mEditText.setSelection(mEditText.length()); // last resort never to happen
            }
    
            mWannaDeleteHyphen = false;
            mInside = false;
        }
    
        @Override
        public void afterTextChanged(Editable s) {
        }
    
        private String makePrettyString(String string) {
            String number = string.replaceAll("-", "");
            boolean isEndHyphen = string.endsWith("-") && (number.length()%4 == 0);
            return number.replaceAll("(.{4}(?!$))", "$1-") + (isEndHyphen ?"-":"");
        }
    
        private int getCursorPos(String oldString, String newString, int oldPos, boolean isDeleteHyphen) {
            int cursorPos = newString.length();
            if(oldPos != oldString.length()) {
                String stringWithMarker = oldString.substring(0, oldPos) + MARKER + oldString.substring(oldPos);
    
                cursorPos = (makePrettyString(stringWithMarker)).indexOf(MARKER);
                if(isDeleteHyphen)
                    cursorPos -= 1;
            }
            return cursorPos;
        }
    
        public HyphenDelimitTextWatcher(EditText editText) {
            mEditText = editText;
        }
    }
    

    Usage:

        mSomeEditText.addTextChangedListener(new HyphenDelimitTextWatcher(mSomeEditText));
    
    0 讨论(0)
  • 2020-11-29 02:51

    If you want to just group visually the numbers, but you don't want to alter the value of the EditText adding dashes, you can use this Span approach:

    EditText editText = findViewById(R.id.editText);
    editText.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 editable) {
            Object[] paddingSpans = editable.getSpans(0, editable.length(), DashSpan.class);
            for (Object span : paddingSpans) {
                editable.removeSpan(span);
            }
    
            addSpans(editable);
        }
    
        private static final int GROUP_SIZE = 4;
    
        private void addSpans(Editable editable) {
    
            final int length = editable.length();
            for (int i = 1; i * (GROUP_SIZE) < length; i++) {
                int index = i * GROUP_SIZE;
                editable.setSpan(new DashSpan(), index - 1, index,
                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
    });
    

    where the DashSpan class looks like this:

    /**
     * A {@link ReplacementSpan} used for spacing in {@link android.widget.EditText}
     * to space things out. Adds '-'s
     */
    public class DashSpan extends ReplacementSpan {
    
        @Override
        public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, FontMetricsInt fm) {
            float padding = paint.measureText("-", 0, 1);
            float textSize = paint.measureText(text, start, end);
            return (int) (padding + textSize);
        }
    
        @Override
        public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y,
                         int bottom, @NonNull Paint paint) {
            canvas.drawText(text.subSequence(start, end) + "-", x, y, paint);
        }
    }
    

    This way you will have visually the grouping using the dashes, but the getText() will return the text without any grouping.

    To force only numbers you can add the attributes android:digits="0123456789" and android:inputType="number" to the EditText.

    This solution is based on the code of this library.

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