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)
// Омогући подршку за грешке (подеси у 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. За прилагођени приказ грешке можете користити засебни TextView испод EditText-а који постаје видљив при грешци. Овај приступ даје потпуну контролу над стиловима и положајем поруке. На пример, можете поставити поруку са десне стране поља, користити другу боју позадине или додати иконицу са леве стране текста.
У Jetpack Compose-у Error State се реализује кроз параметар isError у OutlinedTextField или TextField. Када је isError = true, оквир постаје црвен и можете приказати текст грешке кроз supportingText. Compose нема уграђено аутоматско чишћење при промени текста — програмер управља стањем грешке ручно кроз remember и mutableStateOf.
За групну грешку (једна порука за више поља, нпр. „Попуните сва обавезна поља“) користи се Snackbar, Dialog или inline блок у горњем делу форме. Групна грешка не замењује Error State појединачних поља, већ га допуњује. Корисник прво види општу поруку, затим тражи конкретна поља са грешкама.
| Начин | Предности | Недостаци | Када користити |
|---|---|---|---|
| TextInputLayout.setError | Стандард, анимација, аутоматско чишћење | Само са 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 иконица грешке је обавезна за приступачност.
Анимација појављивања грешке је уграђена у TextInputLayout: текст излази одоздо са глатком променом провидности. За прилагођену анимацију користите Transition API или MotionLayout. На пример, љуљање поља при грешци привлачи додатну пажњу. Али злоупотреба анимације погоршава UX — довољно је глатко појављивање поруке.
Управљање Error State-ом дели се на две фазе: постављање грешке при валидацији поља и ресетовање грешке при исправљању. У најједноставнијем случају, валидација се позива у TextWatcher.afterTextChanged: ако је вредност неважећа, позива се setError са поруком о грешци. Ако је важећа — setError(null). TextInputLayout аутоматски скрива грешку када setError(null) ресетује стање.
За валидацију форме, грешке се постављају у фази слања форме. Пролазак кроз сва поља, провера сваког, постављање грешака за неважећа поља и фокус на прво грешно поље. Дугме за слање се притом блокира. Ако је форма велика, препоручује се померање екрана до првог поља са грешком и аутоматско постављање фокуса на њега.
Правило single error focus: при слању форме постављајте фокус само на прво поље са грешком. Корисник исправља једну грешку одједном, а након исправке следеће поље са грешком аутоматски добија фокус. Овај корак-по-корак приступ смањује когнитивно оптерећење. Material TextInputLayout при постављању грешке не преузима фокус — то треба урадити ручно кроз requestFocus().
Прва грешка — недостатак isErrorEnabled. Ако setErrorEnabled није позван пре setError-а, распоред може да се помери при појави поруке о грешци. Посебно је критично ако се поље налази на средини екрана — корисник губи позицију скроловања. Увек укључите setErrorEnabled(true) у XML-у кроз app:errorEnabled="true" или програмски пре постављања грешке.
Друга грешка — превише дуга порука о грешци. Дугачак текст се прелама у неколико редова и може прекривати суседна поља. Препоручена дужина поруке о грешци је 20-40 карактера. Ако је потребно више информација, користите helperText (савет) у нормалном стању или tooltip за додатно објашњење. Краткоћа је основа доброг Error State-а.
Трећа грешка — игнорисање приступачности. Error State мора бити доступан за screen reader-е. TextInputLayout аутоматски најављује грешку кроз contentDescription, али прилагођене имплементације то морају урадити ручно. Користите announceForAccessibility() или android:importantForAccessibility за поруке о грешци. TalkBack корисници треба да чују грешку одмах након њеног појављивања.
| Грешка | Проблем | Решење |
|---|---|---|
| Нема isErrorEnabled | Померање распореда при грешци | app:errorEnabled="true" у XML-у |
| Дуга порука | Прекривање суседних поља | 20-40 карактера, helperText за детаље |
| Нема приступачности | 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-а за приступачност.
У Compose-у користите isError = true у OutlinedTextField или TextField. Текст грешке се преноси кроз параметар supportingText. Управљајте стањем кроз mutableStateOf. При промени текста ресетујте isError ручно. Compose нема аутоматско чишћење грешке, за разлику од TextInputLayout-а у View систему.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође