自定义格式编辑文本输入android接受信用卡号
Posted
技术标签:
【中文标题】自定义格式编辑文本输入android接受信用卡号【英文标题】:Custom format edit text input android to accept credit card number 【发布时间】:2011-08-22 07:19:05 【问题描述】:如何让编辑文本接受格式输入
4digitnumber-4dignumber-4dignumber-4dignumber
代码
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; );
);
在添加时工作正常,但删除或编辑会导致问题。
【问题讨论】:
***.com/questions/4172242/live-editing-of-users-input/… ***.com/questions/28314240/…完美解决方案 【参考方案1】:现在这适用于所有删除/编辑操作的软/硬键盘。 tx 4 你的帮助..
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)
);
【讨论】:
但是对于我的代码,当我按下返回键时,代码崩溃了......上面的代码也没有删除空格。【参考方案2】:这是有效的:
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;
);
【讨论】:
不错的解决方案。虽然在进行更改时锁定观察者的较低开销方法只是提供一个编辑布尔值。这就是谷歌在他们的 TextWatcher 实现中所做的。不过,+1。 确实,如果按照谷歌的方法更好,我没有考虑过:/(见那里:grepcode.com/file/repository.grepcode.com/java/ext/…) tx..有没有办法在每次编辑后将光标设置在特定位置,文本的末尾以在编辑文本小部件中指定。? editText.setSelection(code.length());可以。但是您可以在使用 editText.getSelectionStart() 设置文本之前简单地记住位置 这个解决方案会导致递归和堆栈溢出【参考方案3】:如果您想仅对数字进行视觉分组,但又不想更改添加破折号的EditText
的值,则可以使用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);
);
DashSpan
类如下所示:
/**
* 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);
这样,您将使用破折号直观地进行分组,但getText()
将返回没有任何分组的文本。
要强制只使用数字,您可以将属性android:digits="0123456789"
和android:inputType="number"
添加到EditText
。
本方案基于this库的代码。
【讨论】:
【参考方案4】:在我的例子中,下面的代码工作正常。
editTextCreditCard.addTextChangedListener(new FourDigitCardFormatWatcher());
为 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));
希望这会对你有所帮助。
【讨论】:
【参考方案5】:它适用于所有情况,当您插入或删除字符时,格式将始终正确。确保你设置
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("^(\\d4"+space+"1)0,3\\d1,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)
);
【讨论】:
干得好,但不要在 for 循环中连接字符串,使用 StringBuilder `formatted.append(numbersOnly.substring(i, i + 4)).append(space);` 找了2个小时终于找到了,谢谢哥们!!【参考方案6】:在我看来,这里提供的答案不适用于删除、从中间操作等中删除。 这是我的代码。它不限制输入的长度,但似乎可以进行各种插入和删除:
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;
用法:
mSomeEditText.addTextChangedListener(new HyphenDelimitTextWatcher(mSomeEditText));
【讨论】:
【参考方案7】:如果你需要这个效果,你可以在EditText中使用这个code
【讨论】:
【参考方案8】:这是一个格式正则表达式,用于以 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("(\\d4)(?=\\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)
);
【讨论】:
你在发帖前测试过这个吗? @KishanSolanki 是的,我在我的一个项目中使用它并在此处粘贴副本。我无法再访问它,但它工作正常。以上是关于自定义格式编辑文本输入android接受信用卡号的主要内容,如果未能解决你的问题,请参考以下文章