android 数值输入限制_Android EditText 限制输入字符 (数字、字母、标点) 正则表达式的方式实现...

这种方法也很实用,但是前提是这种只能限制你可以输入哪些字符,另外,这种方式我代码不是很推崇,列一个静态的可输入的列表,如果有这种需求的,建议参考下面的方法:

// 设置过滤字符函数(过滤掉我们不需要的字符)

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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值