Android: 如何验证 EditText 输入?

我需要对一系列 EditText 进行表单输入验证。我正在使用 OnFocusChangeListener 在用户键入每个验证之后触发验证,但这并不像最后一个 EditText 所希望的那样。

如果我在输入最终的 EditText 时点击“完成”按钮,那么 InputMethod 就会断开连接,但是从技术上来说,重点从未丢失在 EditText 上(因此验证从未发生)。

最好的解决办法是什么?

我是否应该监视 InputMethod 何时从每个 EditText 解除绑定,而不是监视焦点何时更改? 如果应该,如何监视?

353446 次浏览

你为什么不用 TextWatcher

由于你方有多个 EditText盒子需要验证,我认为以下内容适合你方:

  1. 您的活动实现了 android.text.TextWatcher接口
  2. 将 TextChanged 侦听器添加到 EditText 框中
txt1.addTextChangedListener(this);
txt2.addTextChangedListener(this);
txt3.addTextChangedListener(this);
  1. 在重写的方法中,可以按照以下方式使用 afterTextChanged(Editable s)方法
@Override
public void afterTextChanged(Editable s) {
// validation code goes here
}

Editable s实际上无助于查找哪个 EditText 框的文本正在被更改。但是您可以直接检查 EditText 框的内容,如

String txt1String = txt1.getText().toString();
// Validate txt1String

用同样的方法。我希望我说得很清楚,如果我说清楚了,这会有帮助! :)

编辑: 关于更清洁的方法,请参阅下面的 Christopher Perry 的回答

我需要进行字段内验证,而不是字段间验证,以测试我的值在一种情况下是无符号浮点值,在另一种情况下是有符号浮点值。下面是对我有效的方法:

    <EditText
android:id="@+id/x"
android:background="@android:drawable/editbox_background"
android:gravity="right"
android:inputType="numberSigned|numberDecimal"
/>

注意,“ numberSigned | numberDecimal”中不能有任何空格。例如: “ numberSigned | numberDecimal”不起作用。我不知道为什么。

我发现 InputFilter 更适合在 android 上验证文本输入。

这里有一个简单的例子: 如何在 Android 中使用 InputFilter 来限制 EditText 中的字符?

您可以添加一个 Toast 来反馈用户关于您的限制的信息。 还要检查 android: inputType 标记。

如果您希望在发生错误时出现良好的验证弹出窗口和图像,您可以使用 EditText类的 setError方法,正如我所描述的 给你

Screenshot of the use of setError taken from Donn Felker, the author of the linked post

我编写了一个扩展 EditText 的类,它本身支持一些验证方法,实际上非常灵活。

当前,正如我所写的,通过 Xml 属性验证方法支持的 天生的是:

  1. 阿尔法
  2. 字母数字
  3. 数字
  4. 泛型 regexp 泛型 regexp
  5. 字符串空性字符串空性

你可以看看 给你

希望你喜欢:)

TextWatcher 对我来说有点冗长,所以我做了一些更容易下咽的东西:

public abstract class TextValidator implements TextWatcher {
private final TextView textView;


public TextValidator(TextView textView) {
this.textView = textView;
}


public abstract void validate(TextView textView, String text);


@Override
final public void afterTextChanged(Editable s) {
String text = textView.getText().toString();
validate(textView, text);
}


@Override
final public void beforeTextChanged(CharSequence s, int start, int count, int after) { /* Don't care */ }


@Override
final public void onTextChanged(CharSequence s, int start, int before, int count) { /* Don't care */ }
}

像这样使用它:

editText.addTextChangedListener(new TextValidator(editText) {
@Override public void validate(TextView textView, String text) {
/* Validation code here */
}
});

这是从 给你得到的不错的解决方案

InputFilter filter= new InputFilter() {
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
for (int i = start; i < end; i++) {
String checkMe = String.valueOf(source.charAt(i));


Pattern pattern = Pattern.compile("[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz123456789_]*");
Matcher matcher = pattern.matcher(checkMe);
boolean valid = matcher.matches();
if(!valid){
Log.d("", "invalid");
return "";
}
}
return null;
}
};


edit.setFilters(new InputFilter[]{filter});

为了减少验证逻辑的冗长,我编写了一个 安卓程序库。它使用注释和内置规则处理大部分日常验证。有限制,如 @TextRule@NumberRule@Required@Regex@Email@IpAddress@Password等,

您可以将这些注释添加到 UI 小部件引用并执行验证。它还允许您异步执行验证,这对于从远程服务器检查唯一用户名等情况非常理想。

项目主页上有一个关于如何使用注释的示例。您还可以阅读 相关的博客文章,其中我已经编写了关于如何编写验证自定义规则的示例代码。

下面是一个简单的示例,描述了库的用法。

@Required(order = 1)
@Email(order = 2)
private EditText emailEditText;


@Password(order = 3)
@TextRule(order = 4, minLength = 6, message = "Enter at least 6 characters.")
private EditText passwordEditText;


@ConfirmPassword(order = 5)
private EditText confirmPasswordEditText;


@Checked(order = 6, message = "You must agree to the terms.")
private CheckBox iAgreeCheckBox;

该库是可扩展的,您可以通过扩展 Rule类来编写自己的规则。

当用户在键盘上点击“完成”按钮时,你可以通过聆听获得想要的行为,也可以在我的文章 “ Android 表单验证-正确的方式”中查看使用 EditText 的其他技巧

示例代码:

mTextView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
validateAndSubmit();
return true;
}
return false;
}});

这个看起来很有希望,正是医生要我做的:

EditText 验证器

    public void onClickNext(View v) {
FormEditText[] allFields    = { etFirstname, etLastname, etAddress, etZipcode, etCity };
    

    

boolean allValid = true;
for (FormEditText field: allFields) {
allValid = field.testValidity() && allValid;
}
    

if (allValid) {
// YAY
} else {
// EditText are going to appear with an exclamation mark and an explicative message.
}
}

自定义验证器加上这些内置的:

  • Regexp : 用于自定义 regexp
  • Numeric : 仅用于数值字段
  • Alpha : 仅用于 alpha 字段
  • 字母数字 : 猜猜看?
  • PersonName : 检查输入的文本是姓还是名。
  • PersonFullName : 检查输入的值是否为完整的全名。
  • Email : 检查该字段是否为有效电子邮件
  • CreditCard : 使用 Luhn 算法检查字段是否包含有效的信用卡
  • Phone : 检查字段是否包含有效的电话号码
  • DomainName : 检查字段是否包含有效的域名(始终通过 API 级别 < 8的测试)
  • IpAddress : 检查字段是否包含有效的 ip 地址
  • WebUrl : 检查字段是否包含有效的 url (始终通过 API Level < 8中的测试)
  • Date : 检查字段是否为有效的 date/datetime 格式(如果设置了 customFormat,则使用 customFormat 进行检查)
  • Nocheck : 除了字段的空性之外,它不检查任何内容。

在 main.xml 文件中

您可以将以下属性用于验证编辑文本中只能接受的字母表字符。

这样做:

  android:entries="abcdefghijklmnopqrstuvwxyz"

更新方法-TextInputLayout:

谷歌最近推出了设计支持库,有一个组件称为 < strong > TextInputLayout ,它支持通过 setErrorEnabled(boolean)setError(CharSequence)显示错误。

怎么用?

步骤1: 用 TextInputLayout 包装您的 EditText:

  <android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/layoutUserName">


<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="hint"
android:id="@+id/editText1" />


</android.support.design.widget.TextInputLayout>

步骤2: 验证输入

// validating input on a button click
public void btnValidateInputClick(View view) {


final TextInputLayout layoutUserName = (TextInputLayout) findViewById(R.id.layoutUserName);
String strUsername = layoutLastName.getEditText().getText().toString();


if(!TextUtils.isEmpty(strLastName)) {
Snackbar.make(view, strUsername, Snackbar.LENGTH_SHORT).show();
layoutUserName.setErrorEnabled(false);
} else {
layoutUserName.setError("Input required");
layoutUserName.setErrorEnabled(true);
}
}

我已经在我的 Github 仓库上创建了一个示例,如果你愿意的话可以检查这个示例!

我已经为 android 创建了这个库,你可以在其中验证材质设计 EditText 和 EditTextLayout,如下所示:

    compile 'com.github.TeleClinic:SmartEditText:0.1.0'

然后你可以这样使用它:

<com.teleclinic.kabdo.smartmaterialedittext.CustomViews.SmartEditText
android:id="@+id/passwordSmartEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:setLabel="Password"
app:setMandatoryErrorMsg="Mandatory field"
app:setPasswordField="true"
app:setRegexErrorMsg="Weak password"
app:setRegexType="MEDIUM_PASSWORD_VALIDATION" />


<com.teleclinic.kabdo.smartmaterialedittext.CustomViews.SmartEditText
android:id="@+id/ageSmartEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:setLabel="Age"
app:setMandatoryErrorMsg="Mandatory field"
app:setRegexErrorMsg="Is that really your age :D?"
app:setRegexString=".*\\d.*" />

然后你可以像这样检查它是否有效:

    ageSmartEditText.check()

有关更多示例和自定义,请检查存储库 Https://github.com/teleclinic/smartedittext

用于电子邮件和密码验证尝试

  if (isValidEmail(et_regemail.getText().toString())&&etpass1.getText().toString().length()>7){
if (validatePassword(etpass1.getText().toString())) {
Toast.makeText(getApplicationContext(),"Go Ahead".....
}
else{


Toast.makeText(getApplicationContext(),"InvalidPassword".....
}


}else{


Toast.makeText(getApplicationContext(),"Invalid Email".....
}




public boolean validatePassword(final String password){
Pattern pattern;
Matcher matcher;
final String PASSWORD_PATTERN = "^(?=.*[0-9])(?=.*[A-Z])(?=.*
[@#$%^&+=!])(?=\\S+$).{4,}$";
pattern = Pattern.compile(PASSWORD_PATTERN);
matcher = pattern.matcher(password);


return matcher.matches();
}


public final static boolean isValidEmail(CharSequence target) {
if (target == null)
return false;


return android.util.Patterns.EMAIL_ADDRESS.matcher(target).matches();
}