EditText (Java) — Capture Values, Validate, Show Errors & Focus

EditText is the editable text field. In real apps you must: capture values, validate them, show inline errors with setError(), and request focus to the first invalid field. This page shows everything at a micro level with examples.

Common Attributes (Cheat Sheet)

AttributePurposeExample
android:hintPlaceholder text"Email"
android:inputTypeKeyboard & validation hintstextEmailAddress, textPassword, number, phone
android:imeOptionsIME action buttonactionNext, actionDone
android:maxLines / minLinesSingle or multi-line1, 3
android:digitsRestrict allowed characters"0123456789+"
android:autofillHintsSystem autofillemailAddress, password

Example 1 — Basic Form (XML) + Capture Values (Java)

<!-- res/layout/activity_signup.xml -->
<ScrollView
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:fillViewport="true"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <LinearLayout
      android:orientation="vertical"
      android:padding="16dp"
      android:layout_width="match_parent"
      android:layout_height="match_parent">

      <EditText
          android:id="@+id/etName"
          android:hint="Full name"
          android:inputType="textPersonName"
          android:imeOptions="actionNext"/>

      <EditText
          android:id="@+id/etEmail"
          android:hint="Email"
          android:inputType="textEmailAddress"
          android:imeOptions="actionNext"/>

      <EditText
          android:id="@+id/etPassword"
          android:hint="Password"
          android:inputType="textPassword"
          android:imeOptions="actionDone"/>

      <Button
          android:id="@+id/btnSignUp"
          android:text="Sign Up"/>

  </LinearLayout>
</ScrollView>
// SignUpActivity.java — Capture values
public class SignUpActivity extends AppCompatActivity {
  private EditText etName, etEmail, etPassword;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_signup);

    etName = findViewById(R.id.etName);
    etEmail = findViewById(R.id.etEmail);
    etPassword = findViewById(R.id.etPassword);
    Button btn = findViewById(R.id.btnSignUp);

    btn.setOnClickListener(v -> {
      String name = etName.getText().toString().trim();
      String email = etEmail.getText().toString().trim();
      String pass = etPassword.getText().toString();

      // Use values...
      Toast.makeText(this, "Hi "+name, Toast.LENGTH_SHORT).show();
    });
  }
}

Example 2 — Validate & Focus First Invalid Field

This pattern validates in order and stops at the first error. It sets setError() and requestFocus() so users know what to fix.

// SignUpActivity.java — Validation utility
private boolean validateForm() {
  String name = etName.getText().toString().trim();
  String email = etEmail.getText().toString().trim();
  String pass = etPassword.getText().toString();

  // 1) Required
  if (name.isEmpty()) {
    etName.setError("Name is required");
    etName.requestFocus();
    return false;
  }

  // 2) Email format
  if (!android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
    etEmail.setError("Enter a valid email");
    etEmail.requestFocus();
    return false;
  }

  // 3) Password strength
  if (pass.length() < 6) {
    etPassword.setError("Min 6 characters");
    etPassword.requestFocus();
    return false;
  }

  return true;
}
// Call before submit
btn.setOnClickListener(v -> {
  if (validateForm()) {
    // proceed (hide keyboard, call API)
  }
});

Example 3 — Confirm Password & Focus Order

// In XML, add confirm password
<EditText
  android:id="@+id/etConfirm"
  android:hint="Confirm password"
  android:inputType="textPassword"
  android:imeOptions="actionDone"/>
// Java: add confirm logic
EditText etConfirm = findViewById(R.id.etConfirm);

private boolean validatePasswords() {
  String pass = etPassword.getText().toString();
  String confirm = etConfirm.getText().toString();

  if (pass.length() < 6) {
    etPassword.setError("Min 6 characters");
    etPassword.requestFocus();
    return false;
  }
  if (!pass.equals(confirm)) {
    etConfirm.setError("Passwords do not match");
    etConfirm.requestFocus();
    return false;
  }
  return true;
}

Example 4 — Clear Errors While Typing (TextWatcher)

// Attach to each field you want to auto-clear
TextWatcher clearErrorWatcher = new TextWatcher() {
  @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
  @Override public void onTextChanged(CharSequence s, int start, int before, int count) {
    ((EditText) getCurrentFocus()).setError(null);
  }
  @Override public void afterTextChanged(Editable s) {}
};
etEmail.addTextChangedListener(clearErrorWatcher);
etPassword.addTextChangedListener(clearErrorWatcher);
etConfirm.addTextChangedListener(clearErrorWatcher);

Example 5 — InputFilters (Length & Characters)

// Max length 6 + No spaces
InputFilter noSpace = (source, start, end, dest, dstart, dend) -> {
  for (int i = start; i < end; i++) {
    if (Character.isWhitespace(source.charAt(i))) return "";
  }
  return null;
};
etPassword.setFilters(new InputFilter[]{new InputFilter.LengthFilter(16), noSpace});

Example 6 — IME Actions: Move Focus & Submit

// Move focus on Next, submit on Done
etEmail.setOnEditorActionListener((v, actionId, e) -> {
  if (actionId == EditorInfo.IME_ACTION_NEXT) {
    etPassword.requestFocus(); return true;
  }
  return false;
});
etPassword.setOnEditorActionListener((v, actionId, e) -> {
  if (actionId == EditorInfo.IME_ACTION_DONE) {
    if (validateForm() && validatePasswords()) submit();
    return true;
  }
  return false;
});

Example 7 — Show & Hide Keyboard

// Show
etEmail.requestFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(etEmail, InputMethodManager.SHOW_IMPLICIT);

// Hide (e.g., after submit)
View v = getCurrentFocus();
if (v != null) {
  imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}

Example 8 — Phone & OTP Validation

// Phone (basic): 10-15 digits, optional + at start
String phone = etPhone.getText().toString().trim();
if (!phone.matches("^\\+?[0-9]{10,15}$")) {
  etPhone.setError("Invalid phone");
  etPhone.requestFocus();
}

// OTP: exactly 6 digits
String otp = etOtp.getText().toString().trim();
if (!otp.matches("^[0-9]{6}$")) {
  etOtp.setError("Enter 6-digit OTP");
  etOtp.requestFocus();
}

Example 9 — Material TextInputLayout (floating label & errors)

<!-- Add Material dependency in Gradle and wrap your EditText -->
<com.google.android.material.textfield.TextInputLayout
  android:id="@+id/tilEmail"
  android:layout_width="match_parent"
  android:layout_height="wrap_content">

  <com.google.android.material.textfield.TextInputEditText
      android:id="@+id/etEmail"
      android:hint="Email"
      android:inputType="textEmailAddress" />

</com.google.android.material.textfield.TextInputLayout>
// Java: show/hide error on TextInputLayout
TextInputLayout tilEmail = findViewById(R.id.tilEmail);
String email = etEmail.getText().toString().trim();
if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
  tilEmail.setError("Enter a valid email");
  tilEmail.requestFocus();
} else {
  tilEmail.setError(null);
}

Example 10 — All-in-One Submit Flow (Recommended Pattern)

// 1) Collect -> 2) Sanitize -> 3) Validate -> 4) Focus error -> 5) Submit
private void onSubmit() {
  String name = etName.getText().toString().trim();
  String email = etEmail.getText().toString().trim();
  String pass = etPassword.getText().toString();
  String confirm = etConfirm.getText().toString();

  // Required checks
  if (name.isEmpty()) { etName.setError("Required"); etName.requestFocus(); return; }
  if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) { etEmail.setError("Invalid email"); etEmail.requestFocus(); return; }
  if (pass.length() < 6) { etPassword.setError("Min 6 chars"); etPassword.requestFocus(); return; }
  if (!pass.equals(confirm)) { etConfirm.setError("Passwords don’t match"); etConfirm.requestFocus(); return; }

  // Optional: hide keyboard
  View v = getCurrentFocus();
  if (v != null) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
  }

  // TODO: Call API
  Toast.makeText(this, "All good. Submitting...", Toast.LENGTH_SHORT).show();
}

Validation Rules (Quick Table)

RuleCheckExample
Requirednot empty after trim()!text.trim().isEmpty()
EmailAndroid patternPatterns.EMAIL_ADDRESS.matcher(s).matches()
Passwordlength ≥ 6 (or stronger)optionally regex for number+letter
Phonedigits 10–15, optional +"^\\+?[0-9]{10,15}$"
OTPexact digits length"^[0-9]{6}$"
No spacesInputFilterblock whitespace characters

Best Practices

  • Always trim user input before validation or API calls.
  • Fail fast: Validate in order, focus first invalid field, show setError().
  • IME flow: Use imeOptions to move focus (Next) and submit (Done).
  • Use TextInputLayout for floating labels and better UX for errors/helper texts.
  • Sanitize on server too: Client validation is convenience, not security.
  • Accessibility: Provide clear error messages, keep logical focus order, and ensure labels/hints are meaningful.

Practice Tasks

  1. Add a username field: 4–16 chars, letters/numbers/underscore only. Live-validate via TextWatcher.
  2. Build a Reset Password form with email + OTP + new password + confirm, using the same validation & focus flow.
  3. Implement a “Show/Hide password” toggle using Material TextInputLayout.