Error State وضعیتی از فیلد ورودی است که به صورت بصری دادههای نادرست را نشان میدهد. در اندروید Error State از طریق TextInputLayout.setError() پیادهسازی میشود که حاشیه را قرمز کرده و متن خطا را زیر فیلد نمایش میدهد. بر اساس Material Design Guidelines، 2026، Error State باید قابل توجه اما نه تهاجمی باشد: حاشیه قرمز، متن خطا، آیکون. استفاده صحیح از Error State نرخ تبدیل فرمها را 20-30% افزایش میدهد، زیرا کاربر سریع خطاها را پیدا کرده و بدون از دست دادن زمینه، اصلاح میکند.
نکات اصلی
Error State — حالت نمایش ویژه فیلد ورودی است که وقتی دادههای وارد شده از اعتبارسنجی عبور نکنند فعال میشود. از نظر بصری Error State شامل سه مؤلفه است: تغییر رنگ حاشیه یا پسزمینه فیلد (معمولاً به قرمز)، ظاهر شدن پیام متنی زیر فیلد با توضیح خطا و به صورت اختیاری — آیکون یا برجستهسازی. هدف Error State جلب فوری توجه کاربر به فیلد مشکلدار و راهنمایی برای رفع خطا است.
در اندروید 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 یا بلوک درونخطی در بالای فرم استفاده میشود. خطای گروهی جایگزین Error State فیلدهای جداگانه نمیشود، بلکه آن را تکمیل میکند. کاربر ابتدا پیام کلی را میبیند، سپس فیلدهای خاص با خطا را جستجو میکند.
| روش | مزایا | معایب | زمان استفاده |
|---|---|---|---|
| TextInputLayout.setError | استاندارد، انیمیشن، پاکسازی خودکار | فقط با Material Components | گزینه اصلی برای MDC |
| TextView جداگانه | کنترل کامل سبکها | نیاز به مدیریت دستی visibility | تمهای سفارشی، بدون MDC |
| Compose isError | داخلی در Compose | مدیریت دستی وضعیت | پروژههای Jetpack Compose |
| Snackbar/Dialog | پیام گروهی | به فیلد خاصی متصل نیست | تکمیل Error State فیلد |
رنگ Error State در Material Design Components از طریق ویژگی boxStrokeErrorColor یا ویژگی colorError در تم مدیریت میشود. به طور پیشفرض از رنگ قرمز سیستمی استفاده میشود، اما میتوان آن را در تم برنامه یا مستقیماً در TextInputLayout از طریق app:boxStrokeErrorColor="@color/customErrorColor" بازنویسی کرد. برای پشتیبانی از تم تاریک، توصیه میشود از انتخابگر با رنگهای مختلف برای حالت روشن و تاریک استفاده کنید.
آیکون خطا از طریق 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 باید برای صفحهخوانها قابل دسترس باشد. 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) در هر تغییر استفاده کنید.
زیرا فضایی برای پیام خطا ذخیره نشده است. راهحل: 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 از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید