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)
| Attribute | Purpose | Example |
|---|---|---|
| android:hint | Placeholder text | "Email" |
| android:inputType | Keyboard & validation hints | textEmailAddress, textPassword, number, phone |
| android:imeOptions | IME action button | actionNext, actionDone |
| android:maxLines / minLines | Single or multi-line | 1, 3 |
| android:digits | Restrict allowed characters | "0123456789+" |
| android:autofillHints | System autofill | emailAddress, 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)
| Rule | Check | Example |
|---|---|---|
| Required | not empty after trim() | !text.trim().isEmpty() |
| Android pattern | Patterns.EMAIL_ADDRESS.matcher(s).matches() | |
| Password | length ≥ 6 (or stronger) | optionally regex for number+letter |
| Phone | digits 10–15, optional + | "^\\+?[0-9]{10,15}$" |
| OTP | exact digits length | "^[0-9]{6}$" |
| No spaces | InputFilter | block 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
- Add a username field: 4–16 chars, letters/numbers/underscore only. Live-validate via
TextWatcher. - Build a Reset Password form with email + OTP + new password + confirm, using the same validation & focus flow.
- Implement a “Show/Hide password” toggle using Material TextInputLayout.