TextInputLayout هو مكون من مكتبة Material Components لنظام Android يغلف EditText ويضيف إمكانيات متقدمة لإدخال النص. الوظيفة الرئيسية لـ TextInputLayout هي التسمية العائمة (floating label)، التي ترتفع فوق الحقل عند إدخال النص، مما يوفر المساحة ويحسن readability. بالإضافة إلى ذلك، يدعم المكون عرض رسائل الخطأ، الأيقونات داخل الحقل، عداد الأحرف، وأنماط تنسيق متنوعة. وفقًا لإرشادات Material Design (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 (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 (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. سوف نقدم لك النصح ونقترح أفضل حل.