TextInputLayout เป็นคอมโพเนนต์จากไลบรารี Material Components สำหรับ Android ที่ห่อหุ้ม EditText และเพิ่มความสามารถในการป้อนข้อความขั้นสูง ฟังก์ชันหลักของ TextInputLayout คือป้ายลอย (floating label) ซึ่งจะลอยขึ้นเหนือฟิลด์เมื่อมีการป้อนข้อความ ประหยัดพื้นที่และเพิ่มความสามารถในการอ่าน นอกจากนี้ คอมโพเนนต์ยังรองรับการแสดงข้อความข้อผิดพลาด ไอคอนภายในฟิลด์ ตัวนับตัวอักษร และตัวเลือกสไตล์ต่างๆ ตาม Material Design Guidelines (2025) TextInputLayout เป็นวิธีที่แนะนำในการสร้างฟิลด์ข้อความในแอป Android ที่สอดคล้องกับมาตรฐาน Material Design 3
ประเด็นสำคัญ
TextInputLayout คือ ViewGroup จากแพ็คเกจ com.google.android.material.textfield ที่ขยาย LinearLayout และมี EditText อยู่ภายใน คอมโพเนนต์นี้เป็นส่วนหนึ่งของไลบรารี Material Components สำหรับ Android ตั้งแต่เวอร์ชัน 1.0.0 เป้าหมายหลักของ TextInputLayout คือการให้การใช้งานฟิลด์ข้อความ Material Design ที่พร้อมใช้งานโดยใช้ความพยายามน้อยที่สุดจากนักพัฒนา
แตกต่างจาก EditText มาตรฐาน TextInputLayout จัดการแอนิเมชันของป้ายลอย ซึ่งถูกกำหนดผ่านแอตทริบิวต์ android:hint ของ EditText ภายใน เมื่อฟิลด์ว่างเปล่า ป้ายจะแสดงภายในฟิลด์เป็นคำใบ้ปกติ ทันทีที่ผู้ใช้เริ่มพิมพ์ ป้ายจะเคลื่อนที่อย่างมีแอนิเมชันไปยังส่วนบนของฟิลด์ โดยลดขนาดลง ตาม Material Design Guidelines (2025) แอนิเมชันนี้ช่วยปรับปรุงการรับรู้แบบฟอร์มเนื่องจากผู้ใช้จะเห็นชื่อฟิลด์เสมอ แม้หลังจากป้อนข้อมูลแล้ว
ในเชิงสถาปัตยกรรม TextInputLayout ใช้รูปแบบ decorator: มันสกัดกั้นเหตุการณ์ EditText จัดการการแสดงองค์ประกอบเพิ่มเติม (ป้าย ข้อผิดพลาด ไอคอน ตัวนับ) และประสานงานแอนิเมชันของพวกเขา EditText ภายในสามารถเข้าถึงได้ผ่านเมธอด getEditText() และสามารถกำหนดค่าด้วยแอตทริบิวต์มาตรฐาน รวมถึง inputType, maxLines และ hint
<!-- Basic TextInputLayout markup -->
@+id/tilEmail
android:layout_width="match_parent"
android:layout_height="wrap_content">
@+id/etEmail
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Email"
android:inputType="textEmailAddress" />
</com.google.android.material.textfield.TextInputLayout>
ป้ายลอย (floating label) คือคุณสมบัติหลักของ TextInputLayout เมื่อฟิลด์ว่างเปล่า ข้อความจาก android:hint จะแสดงภายใน EditText เป็นตัวยึดตำแหน่งปกติ เมื่อฟิลด์ได้รับการโฟกัสหรือมีการป้อนข้อความ ป้ายจะลอยขึ้นไปยังส่วนบนของ TextInputLayout ลดขนาดฟอนต์และเปลี่ยนสี พฤติกรรมนี้แก้ปัญหาคำใบ้ที่มองไม่เห็นหลังจากผู้ใช้เริ่มพิมพ์
การกำหนดค่าป้ายลอย ทำผ่านแอตทริบิวต์ของ TextInputLayout: app:hintEnabled กำหนดว่าป้ายลอยถูกเปิดใช้หรือไม่ (ค่าเริ่มต้น true), app:hintAnimationEnabled เปิดหรือปิดแอนิเมชันการเปลี่ยน, app:expandedHintEnabled อนุญาตให้แสดงป้ายแม้ว่าฟิลด์จะว่างเปล่าและไม่ได้รับการโฟกัส สีของป้ายในสถานะต่างๆ ถูกจัดการผ่านสไตล์ colorPrimary และ colorControlHighlight
ตามทีม Google Material Components (2025) ป้ายลอยมีประโยชน์โดยเฉพาะอย่างยิ่งในแบบฟอร์มที่มีหลายฟิลด์ ซึ่งผู้ใช้อาจลืมชื่อฟิลด์หลังจากเริ่มพิมพ์ แตกต่างจาก android:hint ธรรมดาที่หายไปเมื่อป้อนข้อมูล ป้ายลอยยังคงมองเห็นได้ตลอดเวลา ให้บริบทสำหรับแต่ละฟิลด์
| แอตทริบิวต์ | คำอธิบาย | ค่าเริ่มต้น |
|---|---|---|
| hintEnabled | เปิดหรือปิดป้ายลอย | true |
| hintAnimationEnabled | เปิดแอนิเมชันการยก/ลดป้าย | true |
| expandedHintEnabled | แสดงป้ายแม้ว่าฟิลด์จะว่างเปล่าและไม่ได้รับการโฟกัส | false |
| hintTextAppearance | สไตล์ข้อความของป้ายลอย | ธีมแอป |
TextInputLayout มีระบบแสดงข้อผิดพลาดในตัวที่ผสานกับฟิลด์ป้อนข้อมูลอย่างสอดคล้องกัน เมื่อตั้งค่าข้อผิดพลาดผ่านเมธอด setError คอมโพเนนต์จะเน้นฟิลด์ (สีของเส้นหรือโครงร่างเปลี่ยนเป็นสีแดง) และแสดงข้อความข้อผิดพลาดใต้ฟิลด์ ซึ่งช่วยลดความจำเป็นในการใช้ TextView แยกต่างหากสำหรับข้อความข้อผิดพลาด
การจัดการการแสดงข้อผิดพลาด ทำผ่านเมธอด setError(CharSequence) และ setErrorEnabled(boolean) เมื่อเรียก setError พร้อมข้อความ ข้อผิดพลาดจะแสดงทันที เมื่อเรียก setError(null) ข้อผิดพลาดจะถูกซ่อน TextInputLayout ยังรองรับไอคอนข้อผิดพลาดแบบกำหนดเองผ่านแอตทริบิวต์ app:errorIconDrawable และการจัดการสีข้อผิดพลาดผ่าน app:errorTextColor
ตาม Material Design Guidelines (2025) ข้อความข้อผิดพลาดควรเฉพาะเจาะจงและเป็นประโยชน์: แทนที่จะเขียน “การป้อนข้อมูลไม่ถูกต้อง” ให้เขียน “อีเมลต้องมี @” การแสดงข้อผิดพลาดควรเกิดขึ้นหลังจากป้อนข้อมูลเสร็จ (เมื่อเสียโฟกัสหรือหลังจากส่งแบบฟอร์ม) ไม่ใช่แบบเรียลไทม์ — ซึ่งช่วยลดความเครียดของผู้ใช้เมื่อกรอกแบบฟอร์ม
// การตั้งค่าข้อผิดพลาดโดยโปรแกรม
textInputLayout.error = "Password min 8 chars"
// การซ่อนข้อผิดพลาด
textInputLayout.error = null
// การตรวจสอบและตั้งค่าข้อผิดพลาดการตรวจสอบความถูกต้อง
if (email.isNullOrBlank()) {
tilEmail.error = "Email is required"
} else {
tilEmail.error = null
}
TextInputLayout รองรับการแสดงไอคอนทั้งที่จุดเริ่มต้นของฟิลด์ (start icon) และจุดสิ้นสุด (end icon) ไอคอนสามารถทำหน้าที่ต่างๆ ได้: สลับการมองเห็นรหัสผ่าน ล้างฟิลด์ การดำเนินการแบบกำหนดเอง ไอคอนแต่ละประเภทถูกควบคุมโดยแอตทริบิวต์แยกต่างหากและสามารถแทนที่ด้วยไอคอนแบบกำหนดเองผ่านแอตทริบิวต์ app:startIconDrawable หรือ app:endIconDrawable
โหมดไอคอนสิ้นสุด ถูกกำหนดผ่านแอตทริบิวต์ app:endIconMode ซึ่งสามารถรับค่าต่อไปนี้: password_toggle — สลับการมองเห็นรหัสผ่าน, clear_text — ล้างฟิลด์, dropdown_menu — ลูกศรสำหรับรายการแบบเลื่อนลง, custom — ไอคอนแบบกำหนดเอง สำหรับ password_toggle TextInputLayout จะจัดการการสลับ inputType ระหว่าง textPassword และ textVisiblePassword โดยอัตโนมัติ และยังทำแอนิเมชันไอคอนดวงตาด้วย
<!-- TextInputLayout with password toggle icon -->
@+id/tilPassword
android:layout_width="match_parent"
app:endIconMode="password_toggle"
app:passwordToggleTint="@color/primary">
@+id/etPassword
android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout>
Material Components สำหรับ Android มีสองสไตล์หลักสำหรับ TextInputLayout: FilledBox (แบบเติม) และ OutlinedBox (แบบมีโครงร่าง) สไตล์ FilledBox มีพื้นหลังที่เติมด้วยสีและเส้นใต้ฟิลด์ที่เปลี่ยนสีเมื่อได้รับการโฟกัส สไตล์ OutlinedBox มีพื้นหลังโปร่งใสและโครงร่างรอบฟิลด์ทั้งหมด สร้างขอบเขตที่ชัดเจนขึ้นและเหมาะกับแบบฟอร์มที่มีหลายฟิลด์มากกว่า
การเลือกสไตล์ขึ้นอยู่กับการออกแบบแอป: FilledBox แนะนำสำหรับแบบฟอร์มที่ใช้บ่อยเนื่องจากดึงดูดความสนใจไปที่ฟิลด์แต่ละฟิลด์น้อยกว่า OutlinedBox เหมาะสำหรับแบบฟอร์มสั้นๆ (เข้าสู่ระบบ ลงทะเบียน) ซึ่งแต่ละฟิลด์ควรถูกทำเครื่องหมายอย่างชัดเจน สไตล์ถูกกำหนดผ่านแอตทริบิวต์ style ใน XML หรือผ่านธีมแอป
| ลักษณะ | FilledBox | OutlinedBox |
|---|---|---|
| พื้นหลัง | เติมสี (โดยปกติสีเทา) | โปร่งใส |
| ขอบ | เส้นด้านล่าง | โครงร่างรอบฟิลด์ |
| โฟกัส | เส้นหนาขึ้นและเปลี่ยนสี | โครงร่างเปลี่ยนสีและหนาขึ้น |
| คำแนะนำ | แบบฟอร์มที่มีการป้อนข้อมูลบ่อย | แบบฟอร์มสั้น เน้นที่ฟิลด์ |
| สไตล์ | Widget.MaterialComponents.TextInputLayout.FilledBox | Widget.MaterialComponents.TextInputLayout.OutlinedBox |
Material Design 3 (M3) นำเสนอสไตล์ที่อัปเดตสำหรับ TextInputLayout ด้วยการพิมพ์ที่ดีขึ้น โทเค็นสีใหม่ และการรองรับสีไดนามิกของ Material You ใน M3 OutlinedBox กลายเป็นสไตล์ที่แนะนำโดยค่าเริ่มต้น และ FilledBox ได้ปรับระยะห่างภายในและรัศมีขอบให้สอดคล้องกับข้อกำหนดใหม่
ตัวอย่างที่สมบูรณ์ของการใช้งานแบบฟอร์มลงทะเบียนกับ TextInputLayout ซึ่งรวมถึงการตรวจสอบอีเมลและรหัสผ่าน การแสดงข้อผิดพลาด และไอคอนแสดงรหัสผ่าน เมื่อกดปุ่มลงทะเบียน ฟิลด์ทั้งหมดจะถูกตรวจสอบและแสดงข้อความข้อผิดพลาดที่เกี่ยวข้อง
@+id/tilName
app:boxBackgroundMode="outlined">
@+id/etName
android:hint="Name" />
</...TextInputLayout>
@+id/tilRegEmail
app:boxBackgroundMode="outlined">
@+id/etRegEmail
android:hint="Email"
android:inputType="textEmailAddress" />
</...TextInputLayout>
@+id/tilRegPassword
app:boxBackgroundMode="outlined"
app:endIconMode="password_toggle">
@+id/etRegPassword
android:hint="Password"
android:inputType="textPassword" />
</...TextInputLayout>
private fun validateForm(): Boolean {
var isValid = true
if (etName.text.isNullOrBlank()) {
tilName.error = "Enter your name"
isValid = false
} else {
tilName.error = null
}
val email = etRegEmail.text.toString()
if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
tilRegEmail.error = "Invalid email format"
isValid = false
} else {
tilRegEmail.error = null
}
val password = etRegPassword.text.toString()
if (password.length < 8) {
tilRegPassword.error = "Password min 8 chars"
isValid = false
} else {
tilRegPassword.error = null
}
return isValid
}
คำถามที่พบบ่อย
TextInputLayout พร้อมใช้งานตั้งแต่เวอร์ชัน 1.0.0 ของไลบรารี com.google.android.material สำหรับฟีเจอร์ Material Design 3 ให้ใช้เวอร์ชัน 1.6.0 ขึ้นไป รวม: implementation “com.google.android.material:material:1.12.0” ใน build.gradle ของโมดูล
สีของป้ายลอย ในสถานะโฟกัสถูกควบคุมโดยแอตทริบิวต์ app:hintTextColor หรือผ่านธีมโดยใช้ colorPrimary สำหรับสถานะต่างๆ (โฟกัส ข้อผิดพลาด ปิดใช้งาน) ให้ใช้ตัวเลือกใน res/color/ หรือแอตทริบิวต์ boxStrokeColor, errorTextColor จากไลบรารี Material Components
ตั้งค่าแอตทริบิวต์ app:counterEnabled=“true” และระบุจำนวนตัวอักษรสูงสุดด้วย app:counterMaxLength=“100” TextInputLayout จะแสดงตัวนับที่ด้านล่างของฟิลด์โดยอัตโนมัติ (เช่น “25/100”) สีของตัวนับสามารถกำหนดค่าผ่าน app:counterTextColor และ app:counterOverflowTextColor สำหรับการเกินขีดจำกัด
FilledBox — พื้นหลังเติมด้วยสี เน้นที่เส้นด้านล่าง ใช้พื้นที่ทางการมองเห็นน้อยกว่า OutlinedBox — พื้นหลังโปร่งใสพร้อมโครงร่างรอบฟิลด์ ขอบเขตมองเห็นได้ชัดเจนกว่า FilledBox แนะนำสำหรับฟิลด์ที่ป้อนข้อมูลบ่อย OutlinedBox สำหรับแบบฟอร์มสั้นๆ ที่ความชัดเจนของแต่ละฟิลด์มีความสำคัญ
ได้ ตั้งค่าแอตทริบิวต์ app:hintEnabled=“false” เพื่อปิดการใช้งานป้ายลอย ในกรณีนี้ TextInputLayout จะทำงานเป็นตัวห่อหุ้มปกติสำหรับ EditText โดยคงฟังก์ชันการทำงานของข้อผิดพลาด ไอคอน และตัวนับตัวอักษรไว้ แต่ไม่มีแอนิเมชันป้าย มีประโยชน์สำหรับฟิลด์ที่ไม่ต้องการคำใบ้หรือใช้ป้ายแบบกำหนดเอง
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม