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 หรือบล็อกอินไลน์ที่ด้านบนของฟอร์ม ข้อผิดพลาดกลุ่มไม่ได้แทนที่ 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" สำหรับการรองรับธีมมืด ขอแนะนำให้ใช้ตัวเลือกที่มีสีแตกต่างกันสำหรับโหมดสว่างและมืด
ไอคอนข้อผิดพลาด ถูกกำหนดค่าผ่าน app:errorIconDrawable โดยค่าเริ่มต้นจะแสดงเครื่องหมายอัศเจรีย์ในวงกลม สามารถเปลี่ยนเป็นไอคอนแบบกำหนดเองหรือลบออกทั้งหมดโดยตั้งค่า app:errorIconDrawable="@null" ไอคอนจะแสดงที่ส่วนท้ายของ TextInputLayout และทำหน้าที่เป็นเครื่องหมายภาพเพิ่มเติม ใน Material Design 3 ไอคอนข้อผิดพลาดจำเป็นสำหรับการเข้าถึง
แอนิเมชัน การปรากฏของข้อผิดพลาดถูกสร้างใน TextInputLayout: ข้อความเลื่อนขึ้นจากด้านล่างด้วยการเปลี่ยนแปลงความโปร่งใสอย่างนุ่มนวล สำหรับแอนิเมชันแบบกำหนดเอง ให้ใช้ Transition API หรือ MotionLayout ตัวอย่างเช่น การเขย่าฟิลด์เมื่อเกิดข้อผิดพลาดดึงดูดความสนใจเพิ่มเติม อย่างไรก็ตาม การใช้แอนิเมชันมากเกินไปทำให้ UX แย่ลง — การปรากฏอย่างนุ่มนวลของข้อความก็เพียงพอ
การจัดการ Error State แบ่งออกเป็นสองขั้นตอน: การตั้งค่าข้อผิดพลาดระหว่างการตรวจสอบฟิลด์และการล้างข้อผิดพลาดเมื่อแก้ไข ในกรณีที่ง่ายที่สุด การตรวจสอบถูกเรียกใน TextWatcher.afterTextChanged: หากค่าไม่ถูกต้อง จะเรียก setError พร้อมข้อความข้อผิดพลาด หากถูกต้อง จะเรียก setError(null) TextInputLayout จะซ่อนข้อผิดพลาดโดยอัตโนมัติเมื่อ setError(null) ล้างสถานะ
สำหรับ การตรวจสอบฟอร์ม ข้อผิดพลาดจะถูกตั้งค่าในขั้นตอนการส่งฟอร์ม วนลูปผ่านทุกฟิลด์ ตรวจสอบแต่ละฟิลด์ ตั้งค่าข้อผิดพลาดสำหรับฟิลด์ที่ไม่ถูกต้อง และโฟกัสที่ฟิลด์ที่มีข้อผิดพลาดแรก ปุ่มส่งจะถูกบล็อกระหว่างกระบวนการนี้ หากฟอร์มมีขนาดใหญ่ ขอแนะนำให้เลื่อนไปยังฟิลด์แรกที่มีข้อผิดพลาดและตั้งค่าโฟกัสโดยอัตโนมัติ
กฎ โฟกัสข้อผิดพลาดเดียว: เมื่อส่งฟอร์ม ให้ตั้งค่าโฟกัสเฉพาะฟิลด์แรกที่มีข้อผิดพลาด ผู้ใช้แก้ไขทีละข้อผิดพลาด และหลังจากแก้ไข ฟิลด์ถัดไปที่มีข้อผิดพลาดจะได้รับโฟกัสโดยอัตโนมัติ วิธีการทีละขั้นตอนนี้ช่วยลดภาระทางปัญญา Material TextInputLayout ไม่สกัดกั้นโฟกัสเมื่อตั้งค่าข้อผิดพลาด — ต้องทำด้วยตนเองผ่าน requestFocus()
ข้อผิดพลาดแรก — ขาด isErrorEnabled หากไม่เรียก setErrorEnabled ก่อน setError เค้าโครงอาจขยับเมื่อข้อความข้อผิดพลาดปรากฏ โดยเฉพาะอย่างยิ่งสำคัญหากฟิลด์อยู่กลางหน้าจอ — ผู้ใช้สูญเสียตำแหน่งการเลื่อน เปิดใช้งาน setErrorEnabled(true) เสมอใน XML ผ่าน app:errorEnabled="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) ทุกครั้งที่มีการเปลี่ยนแปลง
เพราะว่า พื้นที่สำหรับข้อความข้อผิดพลาดไม่ได้ถูกสำรองไว้ วิธีแก้: เปิดใช้งาน 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 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม