android 数值输入限制_Android EditText 限制输入字符 (数字、字母、标点) 正则表达式的方式实现...
这种方法也很实用,但是前提是这种只能限制你可以输入哪些字符,另外,这种方式我代码不是很推崇,列一个静态的可输入的列表,如果有这种需求的,建议参考下面的方法://设置过滤字符函数(过滤掉我们不需要的字符)publicstaticString stringFilter(String str)throwsPatternSyntaxException{String regEx ="[/\\:*?...
这种方法也很实用,但是前提是这种只能限制你可以输入哪些字符,另外,这种方式我代码不是很推崇,列一个静态的可输入的列表,如果有这种需求的,建议参考下面的方法:
// 设置过滤字符函数(过滤掉我们不需要的字符)
public static String stringFilter(String str)throws PatternSyntaxException{
String regEx = "[/\\:*?<>|\"\n\t]";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(str);
return m.replaceAll("");
}
int mMaxLenth = 50;
mEditText.addTextChangedListener(new TextWatcher() {
private int cou = 0;
int selectionEnd = 0;
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
cou = before + count;
String editable = mEditText.getText().toString();
String str = stringFilter(editable);
if (!editable.equals(str)) {
mEditText.setText(str);
}
mEditText.setSelection(mEditText.length());
cou = mEditText.length();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void afterTextChanged(Editable s) {
if (cou > mMaxLenth) {
selectionEnd = mEditText.getSelectionEnd();
s.delete(mMaxLenth, selectionEnd);
if(androidVersion.charAt(0)>='4')
{
mEditText.setText(s.toString());
}
}
}
});
转为重点,现在我们的需求是实现只能输入数字、字母(a-z A-Z)、以及部分的英文标点(@#$%^&*.~/\\{\\}|()'\"?>
那如何用正则匹配去做呢?
这里我先列出代码再来解释:
public abstract class PasswordTextWatcher implements TextWatcher {
private static final String LOG_TAG = PasswordTextWatcher.class
.getSimpleName();
// password match rule
private static final String PASSWORD_REGEX = "[A-Z0-9a-z!@#$%^&*.~/\\{\\}|()'\"?>
private boolean mIsMatch;
private CharSequence mResult;
private int mSelectionStart;
private int mSelectionEnd;
private EditText mPasswordEditText;
public PasswordTextWatcher() {};
public PasswordTextWatcher(EditText editText) {
mPasswordEditText = editText;
};
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
mSelectionStart = mPasswordEditText.getSelectionStart();---------①
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
CharSequence charSequence = "";
if ((mSelectionStart + count) <= s.length()) {---------②
charSequence = s.subSequence(mSelectionStart, mSelectionStart
+ count);
}
mIsMatch = pswFilter(charSequence);---------③
if (!mIsMatch) {
String temp = s.toString();
mResult = temp.replace(charSequence, "");---------④
mSelectionEnd = start;
}
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
if (!mIsMatch) {
mPasswordEditText.setText(mResult);---------⑤
mPasswordEditText.setSelection(mSelectionEnd);---------⑥
}
}
/**
* pswFilter: if the param folow the password match rule
*
* @author yanbb
* @param s
* @return
* @since MT 1.0
*/
private boolean pswFilter(CharSequence s) {
if (TextUtils.isEmpty(s)) {---------⑦
return true;
}
Pattern pattern = Pattern.compile(PASSWORD_REGEX);
Matcher matcher = pattern.matcher(s);
if (matcher.matches()) {
return true;
}
return false;
}
public EditText getPasswordEditText() {
return mPasswordEditText;
}
public void setPasswordEditText(EditText passwordEditText) {
this.mPasswordEditText = passwordEditText;
}
}
基本思路就是在beforeTextChanged()的时候记录下光标的位置,这个位置的作用是为了②的截取串,在onTextChanged()的时候,先对输入的字符截取,然后进行③的判断,如果新输入的字符不匹配,那么就进行④步骤去截掉这个不匹配的新串,然后执行到afterTextChanged()的⑤步骤,这里又会触发EditText的输入变化监听,重新执行beforeTextChanged()以及onTextChanged(),此时的变化的串是空的“”,这样的话,就不做处理,也就是⑦存在的原因,不然会一直递归循环调用,导致stackoverflow,在这些步骤完了之后,会调用⑥,这里,我们需要把光标的位置设置到最开始准备输入的位置。
下面是我添加的log版的代码:
public abstract class PasswordTextWatcher implements TextWatcher {
private static final String LOG_TAG = PasswordTextWatcher.class
.getSimpleName();
private boolean mIsMatch;
private CharSequence mResult;
private int mSelectionStart;
private int mSelectionEnd;
private EditText mPswEditText;
public PasswordTextWatcher() {};
public PasswordTextWatcher(EditText editText) {
mPswEditText = editText;
};
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
Log.v(LOG_TAG, "onTextChanged---> s = " + s + "; start = " + start
+ "; before = " + before + "; count = " + count);
Log.v(LOG_TAG,
"onTextChanged --- > SelectionStart = "
+ mPswEditText.getSelectionStart()
+ "; SelectionEnd = " + mPswEditText.getSelectionEnd());
Log.v(LOG_TAG, "getText = " + mPswEditText.getText() + "; mSelectionStart = " + mSelectionStart);
CharSequence charSequence = "";
if ((mSelectionStart + count) <= s.length()) {
charSequence = s.subSequence(mSelectionStart, mSelectionStart + count);
}
Log.v(LOG_TAG, "charSequence = " + charSequence);
Log.v(LOG_TAG, "isMatch = " + mIsMatch);
if (!mIsMatch) {
mIsMatch = pswFilter(charSequence);
String temp = s.toString();
Log.v(LOG_TAG, "temp = " + temp);
mResult = temp.replace(charSequence, "");
Log.d(LOG_TAG, "onTextChanged---> mSelectionEnd = " + mSelectionEnd);
mSelectionEnd = start;
Log.v(LOG_TAG, "result = " + mResult);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
Log.v(LOG_TAG, "beforeTextChanged---> s = " + s + "; start = " + start
+ "; after = " + after + "; count = " + count);
Log.v(LOG_TAG,
"beforeTextChanged --- > SelectionStart = "
+ mPswEditText.getSelectionStart()
+ "; SelectionEnd = " + mPswEditText.getSelectionEnd());
mSelectionStart = mPswEditText.getSelectionStart();
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
Log.v(LOG_TAG, "afterTextChanged ---> s = " + s + "; mIsMatch = " + mIsMatch);
if (!mIsMatch) {
mIsMatch = true;
mPswEditText.setText(mResult);
Log.v(LOG_TAG, "--- befor setSelection --- result = " + mResult);
Log.d(LOG_TAG, "afterTextChanged---> mSelectionEnd = " + mSelectionEnd);
mPswEditText.setSelection(mSelectionEnd);
Log.v(LOG_TAG, "--- after setText --- result = " + mResult);
}
mIsMatch = false;
Log.v(LOG_TAG, "-------------------------------------mSelectionStart = " + mSelectionStart);
}
private boolean pswFilter(CharSequence s) {
if (TextUtils.isEmpty(s)) {
return true;
}
String regex = "[A-Z0-9a-z!@#$%^&*.~/\\{\\}|()'\"?>
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(s);
if (matcher.matches()) {
return true;
}
return false;
}
}
然后下面添加非匹配的的空格“ ”情况的log:
05-28 11:11:35.418: V/PasswordTextWatcher(7526): beforeTextChanged---> s = 1212; start = 4; after = 1; count = 0
05-28 11:11:35.418: V/PasswordTextWatcher(7526): beforeTextChanged --- > SelectionStart = 4; SelectionEnd = 4
05-28 11:11:35.419: V/PasswordTextWatcher(7526): onTextChanged---> s = 1212 ; start = 4; before = 0; count = 1
05-28 11:11:35.419: V/PasswordTextWatcher(7526): onTextChanged --- > SelectionStart = 5; SelectionEnd = 5
05-28 11:11:35.419: V/PasswordTextWatcher(7526): onTextChanged --- >getText = 1212 ; mSelectionStart = 4
05-28 11:11:35.419: V/PasswordTextWatcher(7526): onTextChanged --- > charSequence =
05-28 11:11:35.420: V/PasswordTextWatcher(7526): onTextChanged --- >isMatch = false
05-28 11:11:35.420: V/PasswordTextWatcher(7526): onTextChanged --- >temp =1212
05-28 11:11:35.420: D/PasswordTextWatcher(7526): onTextChanged---> mSelectionEnd = 4
05-28 11:11:35.420: V/PasswordTextWatcher(7526): onTextChanged---> result = 1212
05-28 11:11:35.423: V/PasswordTextWatcher(7526): afterTextChanged ---> s = 1212 ; mIsMatch = false
05-28 11:11:35.423: V/PasswordTextWatcher(7526): beforeTextChanged---> s = 1212 ; start = 0; after = 4; count = 5
05-28 11:11:35.424: V/PasswordTextWatcher(7526): beforeTextChanged --- > SelectionStart = 5; SelectionEnd = 5
05-28 11:11:35.427: V/PasswordTextWatcher(7526): onTextChanged---> s = 1212; start = 0; before = 5; count = 4
05-28 11:11:35.427: V/PasswordTextWatcher(7526): onTextChanged --- > SelectionStart = 0; SelectionEnd = 0
05-28 11:11:35.427: V/PasswordTextWatcher(7526): onTextChanged --- >getText = 1212; mSelectionStart = 5
05-28 11:11:35.427: V/PasswordTextWatcher(7526): onTextChanged --- > charSequence =
05-28 11:11:35.427: V/PasswordTextWatcher(7526): onTextChanged --- >isMatch = true
05-28 11:11:35.430: V/PasswordTextWatcher(7526): afterTextChanged ---> s = 1212; mIsMatch = true
05-28 11:11:35.430: V/PasswordTextWatcher(7526): -------------------------------------mSelectionStart = 5; mSelectionEnd = 4
05-28 11:11:35.430: V/PasswordTextWatcher(7526): --- befor setSelection --- result = 1212
05-28 11:11:35.430: D/PasswordTextWatcher(7526): afterTextChanged---> mSelectionEnd = 4
05-28 11:11:35.430: V/PasswordTextWatcher(7526): --- after setText --- result = 1212
05-28 11:11:35.430: V/PasswordTextWatcher(7526): -------------------------------------mSelectionStart = 5;
这里需要注意点的就是复制粘贴的情况,下面的复制粘贴12的log,之前EditText里面已经有12两个字符了:
05-28 11:11:20.035: V/PasswordTextWatcher(7526): beforeTextChanged---> s = 12; start = 2; after = 1; count = 0
05-28 11:11:20.035: V/PasswordTextWatcher(7526): beforeTextChanged --- > SelectionStart = 2; SelectionEnd = 2
05-28 11:11:20.036: V/PasswordTextWatcher(7526): onTextChanged---> s = 12 ; start = 2; before = 0; count = 1
05-28 11:11:20.036: V/PasswordTextWatcher(7526): onTextChanged --- > SelectionStart = 3; SelectionEnd = 3
05-28 11:11:20.036: V/PasswordTextWatcher(7526): onTextChanged --- >getText = 12 ; mSelectionStart = 2
05-28 11:11:20.036: V/PasswordTextWatcher(7526): onTextChanged --- > charSequence =
05-28 11:11:20.036: V/PasswordTextWatcher(7526): onTextChanged --- >isMatch = false
05-28 11:11:20.037: V/PasswordTextWatcher(7526): onTextChanged --- >temp =12
05-28 11:11:20.037: D/PasswordTextWatcher(7526): onTextChanged---> mSelectionEnd = 2
05-28 11:11:20.037: V/PasswordTextWatcher(7526): onTextChanged---> result = 12
05-28 11:11:20.038: V/PasswordTextWatcher(7526): afterTextChanged ---> s = 12 ; mIsMatch = false
05-28 11:11:20.038: V/PasswordTextWatcher(7526): beforeTextChanged---> s = 12 ; start = 0; after = 2; count = 3
05-28 11:11:20.038: V/PasswordTextWatcher(7526): beforeTextChanged --- > SelectionStart = 3; SelectionEnd = 3
05-28 11:11:20.044: V/PasswordTextWatcher(7526): onTextChanged---> s = 12; start = 0; before = 3; count = 2
05-28 11:11:20.044: V/PasswordTextWatcher(7526): onTextChanged --- > SelectionStart = 0; SelectionEnd = 0
05-28 11:11:20.044: V/PasswordTextWatcher(7526): onTextChanged --- >getText = 12; mSelectionStart = 3
05-28 11:11:20.044: V/PasswordTextWatcher(7526): onTextChanged --- > charSequence =
05-28 11:11:20.044: V/PasswordTextWatcher(7526): onTextChanged --- >isMatch = true
05-28 11:11:20.045: V/PasswordTextWatcher(7526): afterTextChanged ---> s = 12; mIsMatch = true
05-28 11:11:20.045: V/PasswordTextWatcher(7526): -------------------------------------mSelectionStart = 3; mSelectionEnd = 2
05-28 11:11:20.045: V/PasswordTextWatcher(7526): --- befor setSelection --- result = 12
05-28 11:11:20.045: D/PasswordTextWatcher(7526): afterTextChanged---> mSelectionEnd = 2
05-28 11:11:20.046: V/PasswordTextWatcher(7526): --- after setText --- result = 12
05-28 11:11:20.046: V/PasswordTextWatcher(7526): -------------------------------------mSelectionStart = 3; mSelectionEnd = 2
05-28 11:11:20.046: V/PasswordTextWatcher(7526): beforeTextChanged---> s = 12; start = 2; after = 2; count = 0
05-28 11:11:20.046: V/PasswordTextWatcher(7526): beforeTextChanged --- > SelectionStart = 2; SelectionEnd = 2
05-28 11:11:20.047: V/PasswordTextWatcher(7526): onTextChanged---> s = 1212; start = 2; before = 0; count = 2
05-28 11:11:20.047: V/PasswordTextWatcher(7526): onTextChanged --- > SelectionStart = 4; SelectionEnd = 4
05-28 11:11:20.047: V/PasswordTextWatcher(7526): onTextChanged --- >getText = 1212; mSelectionStart = 2
05-28 11:11:20.047: V/PasswordTextWatcher(7526): onTextChanged --- > charSequence = 12
05-28 11:11:20.047: V/PasswordTextWatcher(7526): onTextChanged --- >isMatch = true
05-28 11:11:20.053: V/PasswordTextWatcher(7526): afterTextChanged ---> s = 1212; mIsMatch = true
05-28 11:11:20.053: V/PasswordTextWatcher(7526): -------------------------------------mSelectionStart = 2; mSelectionEnd = 2
对比和输入空格的log可以看出,Android的复制粘贴,其实是会在前面带上一个空格,然后粘贴到EditText的时候,会将真正的内容和空格分开执行EditText监听变化的回调。上面的log可以印证
更多推荐
所有评论(0)