web-dev-qa-db-fra.com

Format personnalisé modifier le texte saisie Android pour accepter le numéro de carte de crédit

comment faire pour que le texte modifié accepte les entrées au format

4digitnumber-4dignumber-4dignumber-4dignumber   

Le code

text.addTextChangedListener(new TextWatcher() {
    int len = 0;
    String string ;
    @Override

    public void afterTextChanged(Editable s) {

        text.setOnKeyListener(new OnKeyListener()
        {   public boolean onKey(View v, int keyCode, KeyEvent event)
            {              
                    if (keyCode == KeyEvent.KEYCODE_DEL)
                    {

                    }
                    else{

                        string = text.getText().toString();
                        len = string.length()+1;
                        if(len%5==0){text.append("-");}

             }

                return false;      }   });
    }
});

fonctionne bien lors de l'ajout, mais la suppression ou l'édition pose problème.

21
Rahul

Maintenant, cela fonctionne très bien pour le clavier logiciel/dur pour toutes les opérations de suppression/édition. Tx 4 ur help ..

package com.and;

import Android.app.Activity;
import Android.app.AlertDialog;
import Android.inputmethodservice.KeyboardView;
import Android.os.Bundle;
import Android.telephony.PhoneNumberFormattingTextWatcher;
import Android.text.Editable;
import Android.text.Selection;
import Android.text.Spannable;
import Android.text.TextWatcher;
import Android.text.format.Formatter;
import Android.text.method.NumberKeyListener;
import Android.view.KeyEvent;
import Android.view.View;
import Android.view.View.OnKeyListener;
import Android.widget.EditText;
import Android.widget.Toast;

public class ccformat extends Activity {

    String a;
    int keyDel;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        final EditText text = (EditText) findViewById(com.and.R.id.editText1);

        text.addTextChangedListener(new TextWatcher() {

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

                boolean flag = true;
                String eachBlock[] = text.getText().toString().split("-");
                for (int i = 0; i < eachBlock.length; i++) {
                    if (eachBlock[i].length() > 4) {
                        flag = false;
                    }
                }
                if (flag) {

                    text.setOnKeyListener(new OnKeyListener() {

                        @Override
                        public boolean onKey(View v, int keyCode, KeyEvent event) {

                            if (keyCode == KeyEvent.KEYCODE_DEL)
                                keyDel = 1;
                            return false;
                        }
                    });

                    if (keyDel == 0) {

                        if (((text.getText().length() + 1) % 5) == 0) {

                            if (text.getText().toString().split("-").length <= 3) {
                                text.setText(text.getText() + "-");
                                text.setSelection(text.getText().length());
                            }
                        }
                        a = text.getText().toString();
                    } else {
                        a = text.getText().toString();
                        keyDel = 0;
                    }

                } else {
                    text.setText(a);
                }

            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count,
                    int after) {
                // TODO Auto-generated method stub

            }

            @Override
            public void afterTextChanged(Editable s) {
            }
        });
    }
}
23
Rahul

Cela fonctionne:

public class EditTextSample extends Activity {
    // This regexp has to be improved, it does not detect case where you have
    // more than 4 digits in a middle group like: 1234-12345-123
    static final Pattern CODE_PATTERN = Pattern.compile("([0-9]{0,4})|([0-9]{4}-)+|([0-9]{4}-[0-9]{0,4})+");

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.edit_text_sample);

        final EditText editText = (EditText) findViewById(R.id.input);
        editText.addTextChangedListener(new TextWatcher() {

            @Override
            public void afterTextChanged(Editable s) {
                Log.w("", "input" + s.toString());

                if (s.length() > 0 && !CODE_PATTERN.matcher(s).matches()) {
                    String input = s.toString();
                    String numbersOnly = keepNumbersOnly(input);
                    String code = formatNumbersAsCode(numbersOnly);

                    Log.w("", "numbersOnly" + numbersOnly);
                    Log.w("", "code" + code);

                    editText.removeTextChangedListener(this);
                    editText.setText(code);
                    // You could also remember the previous position of the cursor
                    editText.setSelection(code.length());
                    editText.addTextChangedListener(this);
                }
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

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

            private String keepNumbersOnly(CharSequence s) {
                return s.toString().replaceAll("[^0-9]", ""); // Should of course be more robust
            }

            private String formatNumbersAsCode(CharSequence s) {
                int groupDigits = 0;
                String tmp = "";
                for (int i = 0; i < s.length(); ++i) {
                    tmp += s.charAt(i);
                    ++groupDigits;
                    if (groupDigits == 4) {
                        tmp += "-";
                        groupDigits = 0;
                    }
                }
                return tmp;
            }
        });
    }
}
20

Dans mon cas, le code ci-dessous fonctionne bien.

editTextCreditCard.addTextChangedListener(new FourDigitCardFormatWatcher());

Ajouter une classe personnalisée pour TextWatcher .

public class FourDigitCardFormatWatcher implements TextWatcher {

        private static final char space = ' ';

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

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void afterTextChanged(Editable s) {
            if (s.length() > 0 && (s.length() % 5) == 0) {
                final char c = s.charAt(s.length() - 1);
                if (space == c) {
                    s.delete(s.length() - 1, s.length());
                }
            }
            if (s.length() > 0 && (s.length() % 5) == 0) {
                char c = s.charAt(s.length() - 1);
                if (Character.isDigit(c) && TextUtils.split(s.toString(), String.valueOf(space)).length <= 3) {
                    s.insert(s.length() - 1, String.valueOf(space));
                }
            }
        }
    }

J'espère que cela vous aiderait.

2
Hiren Patel

Il me semble que les réponses présentées ici ne fonctionnent pas correctement avec delete, delete from the middle operations, etc. Voici mon code. Cela ne limite pas la longueur des entrées, mais semble être correct avec diverses insertions et suppressions:

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
Mirron

Voici une regex de formatage utilisée pour afficher les détails de la carte au format XXXX XXXX XXXX XXXX

etCreditCardNumber.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) {
                etCreditCardNumber.setFloatingLabel(MaterialEditText.FLOATING_LABEL_HIGHLIGHT);

                String initial = s.toString();
                // remove all non-digits characters
                String processed = initial.replaceAll("\\D", "");

                // insert a space after all groups of 4 digits that are followed by another digit
                processed = processed.replaceAll("(\\d{4})(?=\\d)(?=\\d)(?=\\d)", "$1 ");

                //Remove the listener
                etCreditCardNumber.removeTextChangedListener(this);

                int index = etCreditCardNumber.getSelectionEnd();

                if (index == 5 || index == 10 || index == 15)
                    if (count > before)
                        index++;
                    else
                        index--;

                //Assign processed text
                etCreditCardNumber.setText(processed);

                try {
                    etCreditCardNumber.setSelection(index);
                } catch (Exception e) {
                    e.printStackTrace();
                    etCreditCardNumber.setSelection(s.length() - 1);
                }
                //Give back the listener
                etCreditCardNumber.addTextChangedListener(this);
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });
0
Harpreet

Si vous voulez ne regroupez que visuellement les nombres, mais que vous ne voulez pas modifier la valeur de la EditText ajoutant des tirets, vous pouvez utiliser cette approche Span:

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);
        }
    }
});

où la classe DashSpan ressemble à ceci:

/**
 * 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);
    }
}

De cette façon, vous aurez le regroupement visuel à l’aide des tirets, mais la getText() renverra le texte sans aucun regroupement.

Pour forcer uniquement les nombres, vous pouvez ajouter les attributs Android:digits="0123456789" et Android:inputType="number" à la EditText.

Cette solution est basée sur le code de this library.

0
Roberto Leinardi

Cela fonctionne dans tous les cas, lorsque vous insérez ou supprimez un caractère, le format sera toujours correct. Assurez-vous de définir

Android:inputType="number"

/

myEditText.addTextChangedListener(new TextWatcher() {
        private final String space = "-"; // you can change this to whatever you want
        private final Pattern pattern = Pattern.compile("^(\\d{4}"+space+"{1}){0,3}\\d{1,4}$"); // check whether we need to modify or not
        @Override
        public void onTextChanged(CharSequence s, int st, int be, int count) {
            String currentText = myEditText.getText().toString();
            if (currentText.isEmpty() || pattern.matcher(currentText).matches())
                return; // no need to modify
            String numbersOnly = currentText.trim().replaceAll("[^\\d.]", "");; // remove everything but numbers
            String formatted = "";
            for(int i = 0; i < numbersOnly.length(); i += 4)
                if (i + 4 < numbersOnly.length())
                    formatted += numbersOnly.substring(i,i+4)+space;
                else
                    formatted += numbersOnly.substring(i);
            myEditText.setText(formatted);
            myEditText.setSelection(myEditText.getText().toString().length());
        }
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

        @Override
        public void afterTextChanged(Editable e) {}
});
0
AndroidDev