Error State 是输入字段的一种状态,视觉上提示数据不正确。在 Android 中,Error State 通过 TextInputLayout.setError() 实现,它会将边框高亮为红色并在字段下方显示错误文本。根据 Material Design Guidelines, 2026,Error State 应该醒目但不激进:红色边框、错误文本、图标。正确使用 Error State 可将表单转化率提高 20-30%,因为用户可以在不丢失上下文的情况下快速发现并纠正错误。
要点
Error State 是输入字段的一种特殊显示模式,当输入数据未通过验证时激活。视觉上,Error State 包括三个组成部分:字段边框或背景颜色的变化(通常变为红色)、字段下方出现带有错误描述的文本消息以及可选的图标或高亮。Error State 的目的是立即将用户的注意力吸引到有问题的字段,并建议如何纠正错误。
在 Android 中,Error State 在 Material Design Components 的 TextInputLayout 级别实现。TextInputLayout 包装 EditText 并管理其状态:normal、focused、error、disabled。setError(String) 方法将字段切换到错误状态,更改边框颜色并显示消息。在文本更改或调用 setError(null) 时,字段返回到 normal 状态。
根据 Material Design Guidelines,Error State 应该醒目但不占主导。边框的红色应与正常状态形成对比,但不要使界面过载。错误消息应包含有关问题及其解决方式的具体信息。错误图标(例如带有感叹号的红色圆圈)可加强视觉信号。
setError(CharSequence errorText) 方法将 TextInputLayout 切换到错误状态。errorText 参数是显示在字段下方的文本。如果传递 null,则错误重置。TextInputLayout 管理动画:错误文本以平滑过渡出现,边框变为红色。错误图标(默认为圆圈中的感叹号)显示在字段末尾。
重要细节:setErrorEnabled(true) 应在 setError 之前调用,以预留错误消息的空间。否则,当错误出现时,布局可能会跳跃,因为消息的空间未被保留。建议始终在 XML 中通过 app:errorEnabled="true" 启用错误支持,以避免布局移动。
如果启用了 setErrorEnabled(true) 选项,setError 方法会在字段文本更改时自动重置。这种行为对于实时验证很方便:一旦用户开始纠正错误,红色边框消失,字段返回到正常状态。然而,对于复杂场景,这种自动重置可能是不希望的 — 在这种情况下,请手动管理错误。
val til = findViewById<TextInputLayout>(R.id.til_email)
// 启用错误支持(否则在 XML 中设置)
til.isErrorEnabled = true
// 设置错误消息
til.error = "Invalid email address"
// 清除错误
til.error = null
// 检查是否存在错误
if (til.error != null) {
// 字段处于错误状态
}
在此示例中,使用 Kotlin 属性访问 setError/isErrorEnabled。TextInputLayout 自动更新 UI:更改 boxStrokeColor 颜色,显示错误图标,显示错误文本。如果您更改 EditText 中的文本,错误将自动重置。要手动重置,请设置 error = null。
并非所有项目都使用 Material Design Components。对于自定义错误显示,您可以在 EditText 下方使用单独的 TextView,该 TextView 在错误时变为可见。这种方法可以完全控制样式和消息位置。例如,您可以将消息放在字段右侧,使用不同的背景颜色,或在文本左侧添加图标。
在 Jetpack Compose 中,Error State 通过 OutlinedTextField 或 TextField 中的 isError 参数实现。当 isError = true 时,边框变为红色,您可以通过 supportingText 显示错误文本。Compose 没有内置的文本更改自动清除功能 — 开发人员通过 remember 和 mutableStateOf 手动管理错误状态。
对于组错误(多个字段的一条消息,例如"填写所有必填字段"),使用 Snackbar、Dialog 或表单顶部的内联块。组错误不会取代单个字段的 Error State,而是补充它。用户首先看到一般消息,然后查找带有错误的具体字段。
| 方法 | 优点 | 缺点 | 何时使用 |
|---|---|---|---|
| TextInputLayout.setError | 标准、动画、自动清除 | 仅适用于 Material Components | MDC 的主要选项 |
| 单独 TextView | 完全控制样式 | 需要手动管理可见性 | 自定义主题,无 MDC |
| Compose isError | 内置于 Compose | 手动状态管理 | Jetpack Compose 项目 |
| Snackbar/Dialog | 组消息 | 未绑定到特定字段 | 字段 Error State 的补充 |
Material Design Components 中 Error State 的颜色通过 boxStrokeErrorColor 属性或主题中的 colorError 属性管理。默认使用系统红色,但可以在应用程序主题中或直接在 TextInputLayout 中通过 app:boxStrokeErrorColor="@color/customErrorColor" 覆盖。为了支持深色主题,建议使用选择器为浅色和深色模式设置不同的颜色。
错误图标通过 app:errorIconDrawable 配置。默认显示圆圈中的感叹号。可以替换为自定义图标,或通过设置 app:errorIconDrawable="@null" 完全移除。图标显示在 TextInputLayout 的末尾,作为额外的视觉标记。在 Material Design 3 中,错误图标对于无障碍访问是必需的。
动画错误出现内置于 TextInputLayout 中:文本从下方出现,透明度逐渐变化。对于自定义动画,请使用 Transition API 或 MotionLayout。例如,错误时字段抖动会吸引更多注意。但过度使用动画会降低用户体验 — 平滑的消息出现就足够了。
Error State 的管理分为两个阶段:字段验证时设置错误和纠正时重置错误。在最简单的情况下,验证在 TextWatcher.afterTextChanged 中调用:如果值无效,则调用带错误消息的 setError。如果有效 — setError(null)。当 setError(null) 重置状态时,TextInputLayout 自动隐藏错误。
对于表单验证,错误在表单提交阶段设置。遍历所有字段,检查每个字段,为无效字段设置错误,并聚焦到第一个错误字段。提交按钮在此过程中被阻止。如果表单很大,建议将屏幕滚动到第一个有错误的字段并自动聚焦到它。
Single error focus 规则:提交表单时,仅聚焦到第一个错误字段。用户一次纠正一个错误,纠正后下一个错误字段自动获得聚焦。这种逐步方法减轻了认知负担。Material TextInputLayout 在设置错误时不拦截焦点 — 这需要通过 requestFocus() 手动完成。
第一个错误 — 缺少 isErrorEnabled。如果 setErrorEnabled 未在 setError 之前调用,布局可能会在错误消息出现时移动。如果字段位于屏幕中间,这一点尤其关键 — 用户会丢失滚动位置。始终在 XML 中通过 app:errorEnabled="true" 或在设置错误之前以编程方式启用 setErrorEnabled(true)。
第二个错误 — 错误消息过长。长文本会换行到多行,可能覆盖相邻字段。建议的错误消息长度为 20-40 个字符。如果需要更多信息,请在正常状态下使用 helperText(提示)或使用工具提示进行额外解释。简洁是良好 Error State 的基础。
第三个错误 — 忽略无障碍访问。Error State 必须对屏幕阅读器可访问。TextInputLayout 通过 contentDescription 自动宣布错误,但自定义实现需要手动执行此操作。对错误消息使用 announceForAccessibility() 或 android:importantForAccessibility。TalkBack 用户应在错误出现后立即听到它。
| 错误 | 问题 | 解决方案 |
|---|---|---|
| 缺少 isErrorEnabled | 错误时布局移动 | app:errorEnabled="true" 在 XML 中 |
| 消息过长 | 覆盖相邻字段 | 20-40 字符,详细信息使用 helperText |
| 缺少无障碍访问 | 屏幕阅读器听不到错误 | 对 TalkBack 用户很重要 |
| 未经检查的自动重置 | 字段被错误地视为有效 | 手动管理错误重置 |
常见问题
如果使用 TextInputLayout,请调用 setError(null)。启用 setErrorEnabled(true) 以便消息下方的空间保持保留,但文本消失。在 EditText 中更改文本时,TextInputLayout 会自动重置错误。要手动管理,请使用 addTextChangedListener 并在每次更改时调用 setError(null)。
因为错误消息的空间未被保留。解决方案:在 XML 中为 TextInputLayout 启用 app:errorEnabled="true"。这将为消息保留空间,布局不会移动。如果错误未激活,空间保持为空,但布局稳定。
在 XML 中使用 app:boxStrokeErrorColor 属性,或通过 til.setBoxStrokeErrorStateList() 以编程方式设置。颜色可以使用选择器为不同状态设置。您还可以覆盖应用程序主题中的系统 colorError 属性,以全局更改所有字段的错误颜色。
可以,使用 app:errorEnabled="true" 和 setError() — 但将 boxStrokeErrorColor 覆盖为字段的主色。图标和错误文本仍将可见,但边框保持原始颜色。然而,这会降低错误的可见性,这与 Material Design 的无障碍访问建议相悖。
在 Compose 中,在 OutlinedTextField 或 TextField 中使用 isError = true。错误文本通过 supportingText 参数传递。通过 mutableStateOf 管理状态。在文本更改时,手动重置 isError。与 View 系统中的 TextInputLayout 不同,Compose 没有自动清除错误的功能。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。