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 реализован на уровне TextInputLayout из Material Design Components. 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", чтобы избежать сдвига макета.
Метод setError автоматически сбрасывается при изменении текста поля, если включена опция setErrorEnabled(true). Это поведение удобно для валидации в реальном времени: как только пользователь начинает исправлять ошибку, красная рамка исчезает, и поле возвращается в нормальное состояние. Однако для сложных сценариев этот автосброс может быть нежелателен — в таких случаях управляйте ошибкой вручную.
val til = findViewById<TextInputLayout>(R.id.til_email)
// Enable error support (set in XML otherwise)
til.isErrorEnabled = true
// Set error message
til.error = "Invalid email address"
// Clear error
til.error = null
// Check if error exists
if (til.error != null) {
// Field is in error state
}
В примере используются свойства Kotlin для доступа к setError/isErrorEnabled. TextInputLayout автоматически обновляет UI: меняет цвет boxStrokeColor, показывает error-иконку, отображает текст ошибки. Если изменить текст в EditText, ошибка сбрасывается автоматически. Для ручного сброса присвойте error = null.
Не все проекты используют Material Design Components. Для кастомного отображения ошибки можно использовать отдельный TextView под EditText, который становится видимым при ошибке. Этот подход даёт полный контроль над стилями и расположением сообщения. Например, можно разместить сообщение справа от поля, использовать другой цвет фона или добавить иконку слева от текста.
В Jetpack Compose Error State реализуется через параметр isError в OutlinedTextField или TextField. При isError = true рамка становится красной, и можно показать текст ошибки через supportingText. Compose не имеет встроенного auto-clear при изменении текста — разработчик управляет состоянием ошибки вручную через remember и mutableStateOf.
Для групповой ошибки (одно сообщение для нескольких полей, например, "Заполните все обязательные поля") используется Snackbar, Dialog или inline-блок в верхней части формы. Групповая ошибка не заменяет Error State отдельных полей, а дополняет его. Пользователь сначала видит общее сообщение, затем ищет конкретные поля с ошибками.
| Способ | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
| TextInputLayout.setError | Стандарт, анимация, auto-clear | Только с Material Components | Основной вариант для MDC |
| Отдельный TextView | Полный контроль стилей | Нужно управлять видимостью вручную | Кастомные темы, без MDC |
| Compose isError | Встроено в Compose | Ручное управление состоянием | Проекты на Jetpack Compose |
| Snackbar/Dialog | Групповое сообщение | Не привязано к конкретному полю | Дополнение к Error State поля |
Цвет Error State в Material Design Components управляется через атрибут boxStrokeErrorColor или атрибут colorError в теме. По умолчанию используется системный красный цвет, но его можно переопределить в теме приложения или непосредственно в TextInputLayout через app:boxStrokeErrorColor="@color/customErrorColor". Для поддержки тёмной темы рекомендуется использовать селектор с разными цветами для light и dark режимов.
Иконка ошибки настраивается через app:errorIconDrawable. По умолчанию отображается восклицательный знак в круге. Можно заменить на кастомную иконку или убрать совсем, установив app:errorIconDrawable="@null". Иконка отображается в конце TextInputLayout и служит дополнительным визуальным маркером. В Material Design 3 иконка ошибки обязательна для accessibility.
Анимация появления ошибки встроена в TextInputLayout: текст выезжает снизу с плавным изменением прозрачности. Для кастомной анимации используйте Transition API или MotionLayout. Например, покачивание поля при ошибке привлекает дополнительное внимание. Но злоупотребление анимацией ухудшает UX — достаточно плавного появления сообщения.
Управление Error State делится на два этапа: установка ошибки при валидации поля и сброс ошибки при исправлении. В простейшем случае валидация вызывается в TextWatcher.afterTextChanged: если значение невалидно, вызывается setError с сообщением об ошибке. Если валидно — setError(null). TextInputLayout автоматически скрывает ошибку, когда setError(null) сбрасывает состояние.
Для Form Validation ошибки устанавливаются на этапе отправки формы. Проход по всем полям, проверка каждого, установка ошибок для невалидных полей и фокус на первом ошибочном поле. Кнопка отправки при этом блокируется. Если форма большая, рекомендуется прокрутить экран к первому полю с ошибкой и автоматически установить на него фокус.
Правило single error focus: при отправке формы устанавливайте фокус только на первое поле с ошибкой. Пользователь исправляет одну ошибку за раз, и после исправления следующее поле с ошибкой автоматически получает фокус. Такой пошаговый подход снижает когнитивную нагрузку. Material TextInputLayout при установке ошибки не перехватывает фокус — это нужно делать вручную через requestFocus().
Первая ошибка — отсутствие isErrorEnabled. Если setErrorEnabled не вызван до setError, макет может сдвинуться при появлении сообщения об ошибке. Особенно критично, если поле находится в середине экрана — пользователь теряет позицию скролла. Всегда включайте setErrorEnabled(true) в XML через app:errorEnabled="true" или программно перед установкой ошибки.
Вторая ошибка — слишком длинное сообщение об ошибке. Длинный текст переносится на несколько строк и может перекрывать соседние поля. Рекомендуемая длина сообщения об ошибке — 20-40 символов. Если требуется больше информации, используйте helperText (подсказка) в нормальном состоянии или тултип для дополнительного пояснения. Краткость — основа хорошего Error State.
Третья ошибка — игнорирование accessibility. Error State должен быть доступен для screen readers. TextInputLayout автоматически аннонсирует ошибку через contentDescription, но кастомные реализации должны делать это вручную. Используюте announceForAccessibility() или android:importantForAccessibility для сообщений об ошибке. Пользователи TalkBack должны слышать ошибку сразу после её появления.
| Ошибка | Проблема | Решение |
|---|---|---|
| Нет isErrorEnabled | Сдвиг макета при ошибке | app:errorEnabled="true" в XML |
| Длинное сообщение | Перекрытие соседних полей | 20-40 символов, helperText для деталей |
| Нет accessibility | Screen reader не слышит ошибку | Важно для TalkBack пользователей |
| Автосброс без проверки | Поле ошибочно считается валидным | Ручное управление сбросом ошибки |
Часто задаваемые вопросы
Если используется TextInputLayout, вызовите setError(null). Включите setErrorEnabled(true), чтобы пространство под сообщение оставалось зарезервированным, но текст исчез. При изменении текста в EditText TextInputLayout автоматически сбрасывает ошибку. Для ручного управления используйте addTextChangedListener и setError(null) при каждом изменении.
Потому что место под сообщение об ошибке не зарезервировано. Решение: включите app:errorEnabled="true" в XML для TextInputLayout. Это зарезервирует место под сообщение, и макет не будет сдвигаться. Если ошибка неактивна, место остаётся пустым, но макет стабилен.
Используйте атрибут app:boxStrokeErrorColor в XML или программно через til.setBoxStrokeErrorStateList(). Цвет можно задать селектором для разных состояний. Также можно переопределить системный атрибут colorError в теме приложения, чтобы изменить цвет ошибки глобально для всех полей.
Да, используйте app:errorEnabled="true" и setError() — но переопределите boxStrokeErrorColor на основной цвет поля. Иконка и текст ошибки всё равно будут видны, но рамка останется исходного цвета. Однако это снижает заметность ошибки, что противоречит рекомендациям Material Design по accessibility.
В Compose используйте isError = true в OutlinedTextField или TextField. Текст ошибки передаётся через параметр supportingText. Управляйте состоянием через mutableStateOf. При изменении текста сбрасывайте isError вручную. Compose не имеет auto-clear ошибки, в отличие от TextInputLayout в View-системе.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также