Skip to main content
Android Development with Kotlin
CHAPTER 16 Beginner

User Input, Forms, and Validation

Updated: May 16, 2026
20 min read

# Chapter 16: User Input, Forms, and Validation

1. Introduction

Forms are a crucial part of any application, from login screens and user profiles to e-commerce checkouts. In Android, building forms involves using components like EditText, CheckBox, RadioButton, and Switch. Ensuring that the data users enter is accurate and secure requires robust input validation.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Use various input controls like EditText, CheckBox, and Spinner.
  • Group radio buttons using RadioGroup.
  • Extract and process user input from UI components.
  • Implement form validation logic to ensure data integrity.
  • Provide visual feedback for validation errors.

3. Core Concepts & Implementation

The Input Controls

Android provides several widgets for user input:
  • EditText: For text input (passwords, emails, phone numbers).
  • CheckBox: For multiple-choice selections or boolean toggles (e.g., "Terms and Conditions").
  • RadioGroup & RadioButton: For single-choice selections from a list.
  • Switch: For simple on/off states (e.g., enabling notifications).

Building a Simple Registration Form (XML)

Here is a layout for a basic form:
xml
123456789101112131415161718192021222324252627282930313233343536373839404142
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <EditText
        android:id="@+id/etUsername"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Username"
        android:inputType="textPersonName" />

    <EditText
        android:id="@+id/etEmail"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Email"
        android:inputType="textEmailAddress" />

    <EditText
        android:id="@+id/etPassword"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Password"
        android:inputType="textPassword" />

    <CheckBox
        android:id="@+id/cbTerms"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="I agree to the Terms and Conditions" />

    <Button
        android:id="@+id/btnSubmit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Register"
        android:layout_marginTop="16dp" />

</LinearLayout>

*Note on inputType: This attribute changes the keyboard layout (e.g., showing the '@' symbol for emails).*

Validating Input in Kotlin

When the user clicks the "Register" button, we need to extract the text, check if it meets our criteria, and show an error if it doesn't.
kotlin
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
import android.os.Bundle
import android.util.Patterns
import android.widget.Button
import android.widget.CheckBox
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity

class RegistrationActivity : AppCompatActivity() {

    private lateinit var etUsername: EditText
    private lateinit var etEmail: EditText
    private lateinit var etPassword: EditText
    private lateinit var cbTerms: CheckBox
    private lateinit var btnSubmit: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_registration)

        // Initialize views
        etUsername = findViewById(R.id.etUsername)
        etEmail = findViewById(R.id.etEmail)
        etPassword = findViewById(R.id.etPassword)
        cbTerms = findViewById(R.id.cbTerms)
        btnSubmit = findViewById(R.id.btnSubmit)

        btnSubmit.setOnClickListener {
            validateForm()
        }
    }

    private fun validateForm() {
        val username = etUsername.text.toString().trim()
        val email = etEmail.text.toString().trim()
        val password = etPassword.text.toString()
        val isTermsChecked = cbTerms.isChecked

        // Username validation
        if (username.isEmpty()) {
            etUsername.error = "Username is required"
            etUsername.requestFocus()
            return
        }

        // Email validation
        if (email.isEmpty()) {
            etEmail.error = "Email is required"
            etEmail.requestFocus()
            return
        } else if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
            etEmail.error = "Please enter a valid email"
            etEmail.requestFocus()
            return
        }

        // Password validation
        if (password.length < 6) {
            etPassword.error = "Password must be at least 6 characters"
            etPassword.requestFocus()
            return
        }

        // Checkbox validation
        if (!isTermsChecked) {
            Toast.makeText(this, "You must agree to the terms", Toast.LENGTH_SHORT).show()
            return
        }

        // If all validations pass
        Toast.makeText(this, "Registration Successful!", Toast.LENGTH_SHORT).show()
        // Proceed to next screen or save data...
    }
}

Explanation of Validation Logic

  1. 1. .trim(): Removes leading and trailing whitespaces.
  1. 2. .error: A built-in property of EditText that displays a red warning icon and an error message popup when clicked.
  1. 3. .requestFocus(): Moves the cursor to the field containing the error so the user can fix it immediately.
  1. 4. Patterns.EMAIL_ADDRESS: A built-in Android utility that uses a standard Regular Expression (Regex) to verify if a string looks like an email.

4. Best Practices

  • Validate Early, Validate Often: Provide real-time validation feedback where possible (e.g., using TextWatcher).
  • Use Appropriate Input Types: Always use android:inputType="textEmailAddress", number, or textPassword to provide the correct keyboard to the user.
  • Never Trust User Input: Validate on the client side (Android app) for user experience, but *always* validate again on your backend server for security.
  • Clear Error Messages: Tell the user exactly what went wrong and how to fix it (e.g., "Password must contain a number").

5. Exercises

  1. 1. Create a "Login" form with Email and Password. Validate that both fields are non-empty before allowing a login attempt.
  1. 2. Add a RadioGroup with "Male", "Female", and "Other" options to the registration form. Validate that an option has been selected before submission.

6. Coding Challenge

The Feedback Form Create an application with a Feedback Form. It should contain:
  • A Rating (using a RatingBar or a Spinner with numbers 1-5).
  • A Multi-line EditText for comments (must be at least 20 characters long).
  • An "Anonymous" Switch. If the switch is OFF, require the user to enter their Name. If ON, the Name field should be hidden or disabled.

7. Multiple Choice Questions (MCQs)

  1. 1. Which XML attribute changes the on-screen keyboard to show numbers only?
  • a) android:keyboard="numbers"
  • b) android:inputType="number"
  • c) android:textFormat="integer"
  • d) android:input="digits"
  1. 2. How do you display a built-in error message popup directly on an EditText in Kotlin?
  • a) editText.setError("Message")
  • b) editText.showError("Message")
  • c) editText.error = "Message"
  • d) Both a and c
  1. 3. Which built-in utility checks if an email format is valid?
  • a) EmailValidator.isValid(email)
  • b) Patterns.EMAIL_ADDRESS.matcher(email).matches()
  • c) String.isEmail()
  • d) Android.util.Email.verify()
  1. 4. What is the main difference between a CheckBox and a RadioButton?
  • a) CheckBoxes are round, RadioButtons are square.
  • b) CheckBoxes are for single-choice, RadioButtons are for multiple-choice.
  • c) RadioButtons within a RadioGroup only allow a single selection, while multiple CheckBoxes can be checked simultaneously.
  • d) RadioButtons cannot trigger events.

8. Interview Questions

  1. 1. How do you listen for text changes in an EditText in real-time?
*Answer*: By adding a TextWatcher to the EditText using addTextChangedListener. This provides callbacks for beforeTextChanged, onTextChanged, and afterTextChanged.
  1. 2. What is the purpose of android:inputType?
*Answer*: It hints to the operating system what kind of keyboard to display (e.g., numeric, email with an '@' symbol, password with hidden characters), improving the user experience and reducing invalid input.
  1. 3. How do you hide the soft keyboard programmatically after a user clicks "Submit"?
*Answer*: You use the InputMethodManager system service to hide the soft input from the window token of the currently focused view.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·