Formato personalizado editar entrada de texto android para aceptar el número de tarjeta de crédito

cómo hacer que el texto de edición acepte la entrada en formato

4digitnumber-4dignumber-4dignumber-4dignumber 

El código

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

funciona bien al agregar, pero eliminar o editar causa un problema.

Ahora esto funciona bien para el teclado suave / duro para todas las operaciones de eliminación / edición. 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) { } }); } } 

Esto está funcionando:

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

En mi caso, el código siguiente está funcionando bien.

 editTextCreditCard.addTextChangedListener(new FourDigitCardFormatWatcher()); 

Agregue una clase personalizada para 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)); } } } } 

Espero que esto te ayude.

Me parece que las respuestas que aquí se presentan no funcionan correctamente con eliminar, eliminar de las operaciones del medio, etc. Aquí está mi código. No restringe la duración de la entrada, pero parece estar bien con varias inserciones y eliminaciones:

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

Uso:

  mSomeEditText.addTextChangedListener(new HyphenDelimitTextWatcher(mSomeEditText)); 

si necesita este efecto, puede usar este código en EditText

enter image description here

Funciona en todos los casos, cuando insertas o quitas un personaje, el formato siempre será el correcto. Asegúrate de configurar

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

Si solo desea agrupar visualmente los números, pero no desea alterar el valor de la sum de guiones de EditText , puede usar este enfoque de EditText :

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

donde la clase DashSpan ve así:

 /** * 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 esta forma, tendrá la agrupación visual utilizando los guiones, pero getText() devolverá el texto sin ninguna agrupación.

Para forzar solo números, puede agregar los atributos android:digits="0123456789" y android:inputType="number" a EditText .

Esta solución se basa en el código de esta biblioteca.