Android:如何验证 EditText 输入?

发布于 2024-08-31 01:48:43 字数 290 浏览 3 评论 0原文

我需要对一系列 EditText 进行表单输入验证。我使用 OnFocusChangeListeners 在用户输入每个内容后触发验证,但这对于最后一个 EditText 的行为并不理想。

如果我在输入最终的 EditText 时单击“完成”按钮,则 InputMethod 将断开连接,但从技术上讲,焦点永远不会丢失在 EditText 上(因此永远不会发生验证)。

最好的解决方案是什么?

我是否应该监视 InputMethod 何时与每个 EditText 解除绑定,而不是何时监视焦点更改?如果是这样,怎么办?

I need to do form input validation on a series of EditTexts. I'm using OnFocusChangeListeners to trigger the validation after the user types into each one, but this doesn't behave as desired for the last EditText.

If I click on the "Done" button while typing into the final EditText then the InputMethod is disconnected, but technically focus is never lost on the EditText (and so validation never occurs).

What's the best solution?

Should I be monitoring when the InputMethod unbinds from each EditText rather than when focus changes? If so, how?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

清醇 2024-09-07 01:48:43

为什么不使用 TextWatcher

由于您有许多 EditText 框需要验证,我认为以下内容适合您:

  1. 您的活动实现 android.text.TextWatcher 接口
  2. 您向 EditText 添加 TextChanged 侦听器在
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 的回答

Why don't you use TextWatcher ?

Since you have a number of EditText boxes to be validated, I think the following shall suit you :

  1. Your activity implements android.text.TextWatcher interface
  2. You add TextChanged listeners to you EditText boxes
txt1.addTextChangedListener(this);
txt2.addTextChangedListener(this);
txt3.addTextChangedListener(this);
  1. Of the overridden methods, you could use the afterTextChanged(Editable s) method as follows
@Override
public void afterTextChanged(Editable s) {
    // validation code goes here
}

The Editable s doesn't really help to find which EditText box's text is being changed. But you could directly check the contents of the EditText boxes like

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

in the same method. I hope I'm clear and if I am, it helps! :)

EDIT: For a cleaner approach refer to Christopher Perry's answer below.

季末如歌 2024-09-07 01:48:43

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

TextWatcher is a bit verbose for my taste, so I made something a bit easier to swallow:

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 */ }
}

Just use it like this:

editText.addTextChangedListener(new TextValidator(editText) {
    @Override public void validate(TextView textView, String text) {
       /* Validation code here */
    }
});
秋凉 2024-09-07 01:48:43

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

使用 setError 的屏幕截图,取自链接帖子的作者 Donn Felker

If you want nice validation popups and images when an error occurs you can use the setError method of the EditText class as I describe here

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

魄砕の薆 2024-09-07 01:48:43

为了减少验证逻辑的冗长性,我编写了一个Android 库。它使用注释和内置规则处理大部分日常验证。有@TextRule、@NumberRule@Required@Regex@Email等约束@IpAddress@Password 等,

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

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

这是一个描述该库的用法的简单示例。

@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 类来编写自己的规则。

In order to reduce the verbosity of the validation logic I have authored a library for Android. It takes care of most of the day to day validations using Annotations and built-in rules. There are constraints such as @TextRule, @NumberRule, @Required, @Regex, @Email, @IpAddress, @Password, etc.,

You can add these annotations to your UI widget references and perform validations. It also allows you to perform validations asynchronously which is ideal for situations such as checking for unique username from a remote server.

There is a example on the project home page on how to use annotations. You can also read the associated blog post where I have written sample codes on how to write custom rules for validations.

Here is a simple example that depicts the usage of the library.

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

The library is extendable, you can write your own rules by extending the Rule class.

更新方法 - TextInputLayout:

Google 最近推出了设计支持库,有一个名为 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 存储库,如果您愿意,请查看示例!

Updated approach - TextInputLayout:

Google has recently launched design support library and there is one component called TextInputLayout and it supports showing an error via setErrorEnabled(boolean) and setError(CharSequence).

How to use it?

Step 1: Wrap your EditText with TextInputLayout:

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

Step 2: Validate input

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

I have created an example over my Github repository, checkout the example if you wish to!

梦在深巷 2024-09-07 01:48:43

这是来自这里

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

This was nice solution from 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}); 
灯下孤影 2024-09-07 01:48:43

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

目前,正如我所写,通过xml属性验证方法本地支持:

  1. alpha
  2. alpha numeric
  3. numeric
  4. generic regexp
  5. string nullness

您可以查看 这里

希望你喜欢它:)

I wrote a class that extends EditText which supports natively some validation methods and is actually very flexible.

Current, as I write, natively supported through xml attributes validation methods are:

  1. alpha
  2. alpha numeric
  3. numeric
  4. generic regexp
  5. string emptyness

You can check it out here

Hope you enjoy it :)

皓月长歌 2024-09-07 01:48:43

我发现 InputFilter 更适合验证 Android 上的文本输入。

这是一个简单的例子:
怎么做我在 Android 中使用 InputFilter 来限制 EditText 中的字符?

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

I find InputFilter to be more appropriate to validate text inputs on android.

Here's a simple example:
How do I use InputFilter to limit characters in an EditText in Android?

You could add a Toast to feedback the user about your restrictions.
Also check the android:inputType tag out.

时间海 2024-09-07 01:48:43

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

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

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

I needed to do intra-field validation and not inter-field validation to test that my values were unsigned floating point values in one case and signed floating point values in another. Here's what seems to work for me:

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

Note, you must not have any spaces inside "numberSigned|numberDecimal". For example: "numberSigned | numberDecimal" won't work. I'm not sure why.

空名 2024-09-07 01:48:43

这看起来真的很有希望,正是文档为我订购的:

EditText Validator

    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:用于自定义正则表达式
  • numeric:用于仅数字字段
  • alpha:用于仅alpha字段
  • alphaNumeric >:你猜怎么着?
  • personName:检查输入的文本是人名还是姓氏。
  • personFullName:检查输入的值是否是完整的全名。
  • 电子邮件:检查该字段是否是有效的电子邮件
  • 信用卡:使用Luhn 算法
  • 电话:检查该字段是否包含有效的电话号码
  • 域名:检查该字段是否包含有效的电话号码域名(始终通过 API Level <8 的测试)
  • ipAddress:检查该字段是否包含有效的 ip 地址
  • webUrl:检查该字段是否包含有效的 url (始终通过 API 级别 <8 )
  • date:检查该字段是否为有效的日期/日期时间格式(如果设置了 customFormat,则使用 customFormat 进行检查)
  • nocheck:除了字段是否为空之外,它不会检查任何内容。

This looks really promising and just what the doc ordered for me:

EditText Validator

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

custom validators plus these built in:

  • regexp: for custom regexp
  • numeric: for an only numeric field
  • alpha: for an alpha only field
  • alphaNumeric: guess what?
  • personName: checks if the entered text is a person first or last name.
  • personFullName: checks if the entered value is a complete full name.
  • email: checks that the field is a valid email
  • creditCard: checks that the field contains a valid credit card using Luhn Algorithm
  • phone: checks that the field contains a valid phone number
  • domainName: checks that field contains a valid domain name ( always passes the test in API Level < 8 )
  • ipAddress: checks that the field contains a valid ip address
  • webUrl: checks that the field contains a valid url ( always passes the test in API Level < 8 )
  • date: checks that the field is a valid date/datetime format ( if customFormat is set, checks with customFormat )
  • nocheck: It does not check anything except the emptyness of the field.
云归处 2024-09-07 01:48:43

在 main.xml 文件中,

您可以放置​​以下属性来验证编辑文本中只能接受字母字符。

这样做:

  android:entries="abcdefghijklmnopqrstuvwxyz"

In main.xml file

You can put the following attrubute to validate only alphabatics character can accept in edittext.

Do this :

  android:entries="abcdefghijklmnopqrstuvwxyz"
夕色琉璃 2024-09-07 01:48:43

当用户点击键盘上的“完成”按钮时,您可以通过监听来获得所需的行为,还可以在我的文章中查看有关使用 EditText 的其他提示 "Android表单验证-正确的方式"

示例代码:

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

You can get desired behavior by listening when user hit "Done" button on keyboard, also checkout other tips about working with EditText in my post "Android form validation - the right way"

Sample code:

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;
    }});  
毁梦 2024-09-07 01:48:43

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

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

for email and password validation try

  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();
}
贪了杯 2024-09-07 01:48:43

我已经为 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

I have created this library for android where you can validate a material design EditText inside and EditTextLayout easily like this:

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

then you can use it like this:

<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.*" />

Then you can check if it is valid like this:

    ageSmartEditText.check()

For more examples and customization check the repository
https://github.com/TeleClinic/SmartEditText

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文