如何在Android中使用数据绑定、Regex和Material进行表单验证

218 阅读8分钟

在Android中使用数据绑定、Regex和Material进行表单验证

当构建一个需要用户提交信息的应用程序时,你需要在将这些数据发送到你的应用程序之前对其进行验证。这就是表单验证的概念所在。

当用户填写电子邮件时,应用程序应该能够检查用户是否提供了一个电子邮件输入。如果没有,就相应地通知用户填写正确的电子邮件格式。应用程序需要从用户那里获得许多数值和具体数据。本指南旨在帮助你了解如何使用Android studio实现这些概念。

前提条件

要开始学习本教程,请确保你具备以下要件。

  • 确保你的电脑上安装了Android Studio。
  • 对用android studio运行Kotlin的基本了解。
  • 对使用Android材料设计库的基本了解。

设置一个安卓项目

为了开始,继续创建一个新的Android Studio项目,并有一个空的活动。确保你选择Kotlin作为你想运行应用程序的语言。

new-android-project

我们将使用Android材质设计库来设置基本的Android表单。因此,你需要让你的项目能够访问这个库。进入你的build.gradle 文件,在dependencies {} 内添加以下库。

implementation 'com.google.android.material:material:1.5.0'

一旦你添加了这个库,Sync 你的项目就可以下载并使这个库可以在你的项目中使用。

创建并添加基本的验证到一个材料表单中

Android材质设计帮助你建立一套交互式的、一致的原则设计。它有许多组件,可以让你实现你最大的设计潜力。

Material拥有必要的组件,允许你创建任何Android表单,同时确保整个应用程序的一致性。我们将创建一个基本的登录材料表单,该表单具有材料表单验证功能。前往你的activity_main.xml 文件并设置XML组件。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:text="WELCOME BACK"
        android:textColor="@color/purple_700"
        android:layout_weight="0.2"
        android:layout_width="match_parent"
        android:gravity="center"
        android:layout_height="0dp"
        android:textSize="28sp"/>

    <LinearLayout
        android:layout_weight="0.4"
        android:layout_width="match_parent"
        android:orientation="vertical"
        android:layout_height="wrap_content">
    </LinearLayout>
</LinearLayout>

我们将在子LinearLayout 里面创建我们的登录表单。一个基本的登录表单有InputText 字段,如电子邮件密码和电话号码。在这种情况下,假设我们想给我们的应用程序添加一个电子邮件字段。我们会使用一个EditText 组件来实现。然而,我们需要确保用户输入的文本是一个电子邮件。

下面是你如何使用材料设计来添加一个电子邮件EditText

<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/login_emailContainer"
    style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="8dp"
    app:errorEnabled="true"
    app:helperText="Required"
    app:helperTextTextColor="@color/design_default_color_error">

<com.google.android.material.textfield.TextInputEditText
    android:hint="Email"
    android:layout_width="match_parent"
    android:id="@+id/login_email"
    android:layout_height="wrap_content"
    android:inputType="textEmailAddress"/>
</com.google.android.material.textfield.TextInputLayout>

这里我们有一个TextInputLayout ,它容纳了一个TextInputEditText ,类型是电子邮件。我们可以用材料属性对这些字段进行基本的表单验证。例如,由于TextInput 应该是Email 类型的,我们可以。

  • 添加一个android:inputType="textEmailAddress" 属性,它将检查文本输入格式是否类似于电子邮件的格式。
  • 一个android:hint="Email" ,向用户显示这个字段需要一个电子邮件输入。
  • 一个app:helperText="Required" ,向用户显示这个字段在提交表单前总是需要的。
  • app:errorEnabled="true" 向用户显示一个错误提示,只要指定的字段没有与该字段相关的必要的有效输入。

我们可以继续向我们的应用程序添加更多的字段。

<com.google.android.material.textfield.TextInputLayout
    app:counterMaxLength="16"
    android:id="@+id/login_passwordContainer"
    android:layout_margin="8dp"
    style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
    app:counterEnabled="true"
    android:layout_width="match_parent"
    app:helperText="Required"
    android:layout_height="wrap_content"
    app:helperTextTextColor="@color/design_default_color_error"
    app:errorEnabled="true"
    app:passwordToggleEnabled="true">

<com.google.android.material.textfield.TextInputEditText
    android:layout_height="wrap_content"
    android:id="@+id/login_password"
    android:layout_width="match_parent"
    android:maxLength="16"
    android:hint="Password"
    android:inputType="textPassword"
    android:lines="1"
    />
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
    app:counterEnabled="true"
    android:id="@+id/login_phoneContainer"
    app:counterMaxLength="10"
    style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
    android:layout_margin="8dp"
    android:layout_width="match_parent"
    app:errorEnabled="true"
    android:layout_height="wrap_content"
    app:helperText="Required"
    app:helperTextTextColor="@color/design_default_color_error">

<com.google.android.material.textfield.TextInputEditText
    
    android:layout_width="match_parent"
    android:id="@+id/login_phone"
    android:layout_height="wrap_content"
    android:inputType="number"
    android:hint="Phone Number"
    android:lines="1"/>
</com.google.android.material.textfield.TextInputLayout>

这里,我们又添加了两个字段:密码和电话号码。我们增加了更多的TextInput 验证检查,确保你的应用程序的输入有输入数据的一致性。

比如说。

  • android:inputType="textPassword" 和 ,表明每个输入字段分别接纳了一个密码和一个数字。android:inputType="number"
  • 属性android:maxLength="16" ,只允许用户输入准确的字符数。当计数器检查和最大字符数达到后,用户就可以向该字段添加更多的字符。
  • app:helperText="Required" 以显示用户在提交表单前需要填写这个字段。
  • app:errorEnabled="true" 来捕捉输入错误和文本不匹配。
  • 我们还添加了一个app:counterMaxLength 。这将检查单个TextInput 的最大字符数。app:counterEnabled="true" 将保持计数并显示这个字符,以便用户可以了解他们可以添加到单个字段的最大字符数。

现在让我们添加一个按钮,它将帮助我们使用Kotlin代码处理复杂的验证逻辑。

<com.google.android.material.button.MaterialButton
    android:layout_marginTop="60dp"
    android:layout_width="290dp"
    android:layout_margin="4dp"
    android:text="Login"
    android:layout_gravity="center"
    android:layout_height="62dp"
    android:id="@+id/login_button"/>

你可以运行你的应用程序来检查上述表单是否正确设置。

form

用数据绑定进行验证

我们已经使用材料来创建和执行基本的表单验证。现在让我们使用数据绑定来在用户提交这些输入之前验证表单输入。

数据绑定是一种机制,它允许你连接不同来源的值。它允许你将XML布局中的用户界面(UI)组件与数据源绑定。这使你能够将用户界面组件与应用逻辑联系起来。

我们可以使用数据绑定的概念来检查表单的有效性。一个表单涉及到向文本字段添加值。因此,我们可以将表单的UI连接到应用域对象,以根据用户的输入自动更新UI。

要在你的Kotlin项目中设置数据绑定,请前往build.gradle 文件并添加以下插件。

plugins {
    id 'kotlin-kapt'
}

然后在android {} 内添加以下数据绑定buildFeatures

buildFeatures{
    viewBinding = true
}

前往MainActivity.kt ,并初始化dataBinding 。首先是ActivityMainBinding ,它反映了tools:context=".MainActivity" 所指定的XML布局上下文。在AppCompatActivity() 的正下方添加以下内容。

private lateinit var activityMainBinding: ActivityMainBinding

然后在onCreate() 方法中初始化ActivityMainBinding 。在这里,我们将用下面两行代码取代通常的setContentView(R.layout.activity_main)

activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)

现在我们可以开始使用数据绑定来验证我们的表单。我们将检查和验证每个字段。

检查密码是否有效

我们将创建一个函数validPassword() ,并使用以下检查来验证密码输入是否有效,基于我们希望用户提交的密码。

private fun validPassword(): String? {
    val passwordText = activityMainBinding.loginPassword.text.toString()
    if(passwordText.length < 8) {
        return "Minimum 8 Character Password"
    }
    if(!passwordText.matches(".*[A-Z].*".toRegex())) {
        return "Must Contain 1 Upper-case Character"
    }
    if(!passwordText.matches(".*[a-z].*".toRegex())) {
        return "Must Contain 1 Lower-case Character"
    }
    if(!passwordText.matches(".*[@#\$%^&+=].*".toRegex())) {
        return "Must Contain 1 Special Character (@#\$%^&+=)"
    }

    return null
}

这是一个简单的检查。当用户输入密码时,它必须至少有八个字符。否则,这将触发一个错误,用户将被要求输入一个至少有八个字符的密码。

在另一端,密码字符计数器将只接受由app:counterMaxLength="16" 指定的最多16个字符的密码。

对于一个标准的密码,建议添加特殊字符并混合小写和大写字母。在这种情况下,我们使用Regex 来验证输入的密码是否有这种字符。如果没有,每个密码验证检查都会向用户端抛出一个错误,并通知他们根据当前的密码值来添加什么。

检查电子邮件是否有效

我们将创建一个函数checkIfEmailIsValid() ,根据我们希望用户提交的电子邮件值检查密码输入是否有效。

private fun checkIfEmailIsValid(): String? {

    val emailInputText = activityMainBinding.loginEmail.text.toString()
    activityMainBinding.loginEmail.doOnTextChanged { text, start, before, count ->
        if(!Patterns.EMAIL_ADDRESS.matcher(emailInputText).matches()){
            activityMainBinding.loginEmail.error = "Invalid Email Address"
        }
        else{
            activityMainBinding.loginEmail.error = null
        }
    }
}

这里我们将使用自定义的EMAIL_ADDRESS 模式。这将检查输入的电子邮件,确保它与有效的电子邮件相匹配。如果用户输入了一个错误的电子邮件,这将返回"Invalid Email Address"

检查电话号码是否有效

我们将创建一个函数checkValidPhoneNumber() ,并验证电话号码的输入是否有效。

private fun checkValidPhoneNumber(): String? {
    val phoneText = activityMainBinding.loginPhone.text.toString()
    if(!phoneText.matches(".*[0-9].*".toRegex())){
        return "Must be all Digits"
    }
    if(phoneText.length != 10){
        return "Must be 10 Digits"
    }
    return null
}

这里,一个电话号码必须是数字。我们使用材料手工指定android:inputType="number" 。这将只允许用户输入数字类型的输入。然而,我们可以在我们的数据绑定中添加一个Regex,以根据用户的输入更新用户界面。我们还指定了app:counterMaxLength="10" 。因此,一个电话号码必须至少是十位数。然而,如果用户输入的数字超过十位,我们要将其作为一个错误返回,并通知用户该字段的电话号码"Must be 10 Digits"

处理表单提交

这个验证将在用户点击登录按钮时被处理。现在让我们把setOnClickListener 添加到loginButton 。我们将创建一个函数login() ,返回一个有效的表单和一个无效的表单提交的错误。

private fun login() {
    activityMainBinding.loginEmailContainer.helperText = checkIfEmailIsValid()
    activityMainBinding.loginPasswordContainer.helperText = validPassword()
    activityMainBinding.loginPhoneContainer.helperText = checkValidPhoneNumber()

    val checkIfEmailIsValid = activityMainBinding.loginEmailContainer.helperText == null
    val validPassword = activityMainBinding.loginPasswordContainer.helperText == null
    val checkValidPhoneNumber = activityMainBinding.loginPhoneContainer.helperText == null

    if (checkIfEmailIsValid && validPassword && checkValidPhoneNumber) {
        Toast.makeText(this,"Valid Form", Toast.LENGTH_SHORT).show()
        resetForm()

    }

    else
        Toast.makeText(this, "Invalid Form", Toast.LENGTH_SHORT).show()
}

在这里我们将把已经添加的输入值与我们的应用域绑定,并检查每个值是否有效。这个检查将在用户点击登录按钮时发生。继续往前走,在onCreate() 方法中加入以下内容:setOnClickListener

activityMainBinding.loginButton.setOnClickListener { login() }

当用户点击loginButton ,而所有的输入值都是有效的,将显示一个祝酒信息Valid Form 。否则,将显示Invalid Form 信息。

当用户成功地提交了有效的值,我们要重置表单的输入。继续创建一个resetForm() 函数,如下图所示。

private fun resetForm() {

    activityMainBinding.loginEmail.text = null
    activityMainBinding.loginPassword.text = null
    activityMainBinding.loginPhone.text = null

    activityMainBinding.loginPasswordContainer.helperText = "Required"
    activityMainBinding.loginEmailContainer.helperText = "Required"
    activityMainBinding.loginPhoneContainer.helperText = "Required"
}

这将清除输入并将其重置为默认值,并有一个"Required" 的帮助文本。

每个字段都会根据错误的输入向用户显示一条信息。例如,如果电子邮件是无效的,我们要更新用户界面并向用户显示电子邮件的值是"Invalid Email Address"

要做到这一点,在所有的表单域函数中添加一个setOnFocusChangeListener 。这样,每个不正确的输入都会以正确的错误信息来更新UI。继续添加以下setOnFocusChangeListener 函数,并根据视图ID将它们绑定到XML UI上。

private fun passwordInputTextOnFocusListener() {
    activityMainBinding.loginPassword.setOnFocusChangeListener { _, focused ->
        if(!focused){
            activityMainBinding.loginPasswordContainer.helperText = validPassword()
        }
    }
}

private fun emailInputTextOnFocusListener() {
    activityMainBinding.loginEmail.setOnFocusChangeListener { _, focused ->
        if(!focused){
            activityMainBinding.loginEmailContainer.helperText = checkIfEmailIsValid()
        }
    }
}

private fun phoneInputTextOnFocusListener() {
    activityMainBinding.loginPhone.setOnFocusChangeListener { _, focused ->
        if(!focused){
            activityMainBinding.loginPhoneContainer.helperText = checkValidPhoneNumber()
        }
    }
}

最后,在onCreate() 方法中调用这些函数。

emailInputTextOnFocusListener()
passwordInputTextOnFocusListener()
phoneInputTextOnFocusListener()

我们的应用程序验证检查已经完成。你可以运行它们来测试所有的工作是否正确。

试着在文本字段中添加数值,并点击登录按钮来验证它们。

invalid-form

如果你根据表单验证提交了正确的输入,这将重置表单并显示你提交的值是有效的。

总结

在本教程中,我们已经涵盖并演示了Android studio中表单验证的基础知识。设置你所需要的用户,这是非常直接的。这可以确保数据的一致性并减少生产错误。

我希望你发现这些工具很有用,测试起来很简单,而且很容易构建应用程序。