InputFilter هي واجهة من Android SDK تتيح اعتراض وتعديل النص المدخل قبل عرضه في EditText. يحدد المطور قواعد التصفية: الأحرف المسموح بها، الحد الأقصى للطول، تنسيق الإدخال. وفقًا لـ Android Developers, 2026، يتم استخدام InputFilter لتقييد إدخال الحروف والأرقام والرموز الخاصة والتنسيق التلقائي للنص. على عكس TextWatcher، يتم تفعيل الفلتر قبل تغيير النص، مما يمنع الإدخال غير الصحيح على مستوى المصدر.
الملخص
InputFilter هي واجهة وظيفية من حزمة android.text تحدد طريقة واحدة filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend). يتم استدعاؤها تلقائيًا في كل مرة يحاول المستخدم كتابة أو لصق أو استبدال نص في EditText. تحدد القيمة المعادة ما إذا كان التغيير سيتم قبوله أو رفضه أو تعديله.
الغرض الرئيسي من InputFilter هو منع الإدخال غير الصحيح قبل وصول النص إلى الحقل. على سبيل المثال، في حقل إدخال أرقام الهاتف، يمكن للفلتر منع الحروف والرموز الخاصة. في حقل كلمة المرور، يمكن فرض حد أدنى للطول. في حقل رمز التحقق، يمكن السماح بالأرقام فقط. على عكس التحقق عبر TextWatcher، يمنع الفلتر ظهور الأحرف الخاطئة على الشاشة تمامًا.
وفقًا لـ Android Developers، يتم استخدام InputFilter في جميع مكونات Material Design الخاصة بـ TextInputEditText. المكتبات مثل PhoneNumberFormattingTextWatcher تجمع بين TextWatcher وInputFilter للتنسيق الكامل. يُوصى باستخدام InputFilter كحاجز أول للحماية من الإدخال غير الصحيح، وTextWatcher للمنطق الإضافي بعد الإدخال.
تستقبل طريقة filter ستة معاملات: source — النص المدخل، start و end — حدود الجزء المدخل، dest — المحتوى الحالي للحقل، dstart و dend — موضع الإدراج. إذا أعادت الطريقة null، يتم قبول التغيير دون تعديل. إذا أعادت سلسلة فارغة «»، يتم حظر التغيير. إذا أعادت CharSequence جديدة، يتم استبدال النص الأصلي بالقيمة المعاد.
على سبيل المثال، إذا حاول مستخدم كتابة حرف «a» في حقل يسمح بالأرقام فقط، يعيد الفلتر «» ولا يظهر الحرف. إذا تم إدخال «123»، قد يعيد الفلتر «1-2-3» مضيفًا فواصل. تتيح هذه الآلية التنسيق التلقائي لأرقام الهواتف والتواريخ والبيانات المنظمة الأخرى دون TextWatcher.
هام: InputFilter لا يعدل مصدر البيانات الأصلي، بل يعيد نسخة مفلترة فقط. Android نفسه يطبق القيمة المعاد على Editable. إذا أعاد الفلتر null، لا يلزم أي إجراءات إضافية. إذا أعاد نصًا معدلاً، يزيل Android النطاق الأصلي ويدرج الجديد.
يوفر Android SDK العديد من التطبيقات المضمنة لـ InputFilter. الأكثر شيوعًا هو InputFilter.LengthFilter، الذي يحد من الحد الأقصى لطول النص. تقبل المنشئة عددًا صحيحًا — الحد الأقصى لعدد الأحرف. إذا تجاوز طول النص الحالي بالإضافة إلى الإدخال الحد، يعيد الفلتر سلسلة مقتطعة، مما يمنع تجاوز الحد.
أيضًا يتوفر InputFilter.AllCaps، الذي يحول جميع الأحرف المدخلة إلى أحرف كبيرة. يُستخدم في حقول الرموز والرموز البريدية والبيانات الأخرى حيث حالة الأحرف مهمة. لا يقوم الفلتر ببساطة بحظر الأحرف الصغيرة بل يحولها، وهو أمر مناسب للمستخدم — حيث يرى نتيجة التحويل.
يوجد InputFilter.LengthFilter لحدود متعددة — من خلال مجموعة من المرشحات. على سبيل المثال، إذا كنت بحاجة إلى تحديد الطول إلى 20 حرفًا والسماح بالأرقام فقط، يمكنك تطبيق LengthFilter + فلتر أرقام مخصص. يتم تنفيذ كل فلتر بالتسلسل، وتصبح نتيجة الفلتر السابق dest للفلتر التالي.
| الفلتر | الغرض | مثال الاستخدام |
|---|---|---|
| LengthFilter | تقييد طول النص | حقل اسم حتى 50 حرفًا |
| AllCaps | تحويل إلى أحرف كبيرة | حقل رمز بريدي |
| InputFilter مخصص | قواعد ترشيح مخصصة | أرقام فقط، لا رموز خاصة |
لإنشاء فلتر مخصص، يجب تنفيذ واجهة InputFilter وإعادة تعريف طريقة filter. مهمة شائعة هي فلتر يسمح بالأرقام فقط. في هذه الحالة، تتحقق الطريقة من كل حرف من source باستخدام Character.isDigit وتعيد سلسلة مفلترة أو null إذا كانت جميع الأحرف صالحة.
class DigitsInputFilter : InputFilter {
override fun filter(
source: CharSequence?,
start: Int,
end: Int,
dest: Spanned?,
dstart: Int,
dend: Int
): CharSequence? {
val sb = StringBuilder()
for (i in start until end) {
val c = source?.get(i)
if (c != null && Character.isDigit(c)) {
sb.append(c)
}
}
return if (sb.length == end - start) null else sb
}
}
مثال DigitsInputFilter يمر عبر جميع أحرف النص المدخل ويحتفظ بالأرقام فقط. إذا اجتازت جميع الأحرف التحقق، تعيد الطريقة null — هذه هي الحالة المثلى لأنها لا تتطلب عمليات ذاكرة إضافية. إذا تم تجاهل بعض الأحرف، يتم إرجاع سلسلة جديدة، وتصل الأرقام فقط إلى EditText.
سيناريو شائع آخر هو فلتر لمنع الرموز الخاصة. التنفيذ مشابه: التحقق من كل حرف عبر Character.isLetterOrDigit أو المقارنة مع قائمة الأحرف المسموح بها. تُستخدم هذه المرشحات في حقول اسم المستخدم وسلاسل البحث والأماكن الأخرى حيث الرموز الخاصة غير مسموحة.
يتم تعيين المرشحات على EditText عبر طريقة setFilters(InputFilter[]). مصفوفة المرشحات تحل محل المصفوفة الحالية، لذلك إذا كنت بحاجة إلى إضافة فلتر إلى المرشحات الموجودة، يجب الحصول على المرشحات الحالية عبر getFilters()، وإنشاء مصفوفة جديدة، وتعيينها مرة أخرى. يحتوي EditText على فلتر افتراضي واحد — LengthFilter، الذي يتم تعيينه عبر android:maxLength في XML.
val editText = findViewById<EditText>(R.id.phone_input)
editText.filters = arrayOf(
DigitsInputFilter(),
InputFilter.LengthFilter(10)
)
في المثال، يتم تعيين فلترين: DigitsInputFilter (أرقام فقط) و LengthFilter (حد أقصى 10 أحرف). ترتيب المرشحات في المصفوفة مهم: يستقبل الفلتر الأول الإدخال الأصلي، يعالجه ويمرر النتيجة إلى الثاني. إذا قام DigitsInputFilter بتصفية بعض الأحرف، يرى LengthFilter النص المفلتر بالفعل ويطبق تقييد الطول عليه.
يمكن أيضًا تعيين المرشحات عبر سمة XML android:inputType، التي تضيف تلقائيًا بعض المرشحات. على سبيل المثال، inputType=«phone» يضيف DigitsKeyListener ويسمح بالأرقام فقط وبعض الرموز الخاصة. ومع ذلك، للتحكم الكامل في التصفية، يُوصى باستخدام setFilters برمجيًا، خاصة عند الجمع بين عدة قواعد.
InputFilter وTextWatcher يؤديان وظائف مختلفة وغالبًا ما يُستخدمان معًا. يعمل InputFilter على مستوى الإدخال — يمنع الأحرف غير الصحيحة من الوصول إلى الحقل. يعمل TextWatcher بعد الإدخال — يسمح بالتفاعل مع التغييرات وإجراء التحقق من القواعد المعقدة وتحديث واجهة المستخدم. مزيج النهجين يعطي أفضل نتيجة.
على سبيل المثال، لحقل إدخال البريد الإلكتروني: يمكن لـ InputFilter منع المسافات والأحرف السيريلية على مستوى الإدخال، بينما يمكن لـ TextWatcher التحقق من الامتثال الكامل لنمط البريد الإلكتروني بعد كل تغيير. الأول يحمي من الأخطاء الواضحة، والثاني من الأخطاء الهيكلية. هذا الفصل في المسؤوليات يجعل الكود أنظف ويقلل من عبء التحقق.
وفقًا لـ Material Design Guidelines، يجب تطبيق المرشحات على الحقول ذات القيود الصارمة: أرقام الهواتف ورموز التحقق وأرقام PIN والرموز البريدية. للحقول ذات التحقق المرن — الاسم والعنوان والتعليق — يكفي TextWatcher وحده لعدم إعاقة المستخدمين عن إدخال قيم مشروعة ولكن غير قياسية.
| المعيار | InputFilter | TextWatcher |
|---|---|---|
| وقت التنشيط | قبل تغيير النص | بعد تغيير النص |
| الغرض | منع الأحرف غير الصالحة | التفاعل مع التغييرات، التحقق، واجهة المستخدم |
| القيمة المعادة | نص مفلتر أو null | لا شيء (void) |
| التطبيق | setFilters() | addTextChangedListener() |
الأسئلة الشائعة
InputFilter يعترض الإدخال قبل تغيير النص ويمكنه حظره أو تعديله. يتم استدعاء TextWatcher بعد التغيير ويسمح بالتفاعل مع القيمة الجديدة. InputFilter حماية وقائية، TextWatcher معالجة لاحقة. للتحقق الكامل من صحة النموذج، يُوصى باستخدام كلا النهجين.
مرر مصفوفة من المرشحات إلى طريقة setFilters(). يتم تنفيذ المرشحات بالتسلسل بترتيب المصفوفة. لتفادي فقدان المرشحات الموجودة، احصل عليها عبر getFilters()، أضف الجديدة إلى نسخة من المصفوفة، ثم عينها مرة أخرى عبر setFilters. لا تستبدل المرشحات دون مراعاة المثبتة بالفعل.
نعم، يمكن لـ InputFilter تعديل الإدخال عن طريق إعادة CharSequence معدلة. على سبيل المثال، يمكن لفلتر رقم الهاتف إضافة مسافات أو أقواس. ومع ذلك، للتنسيق المعقد، من الأفضل الجمع بين InputFilter وTextWatcher، لأن الفلتر موجه للحظر وليس للمعالجة اللاحقة.
أي أحرف: مسافات، حروف، أرقام، رموز خاصة، أحرف Unicode. في فلتر مخصص، تحدد الشرط باستخدام Character.isLetter أو isDigit أو isWhitespace أو تقارن مع قائمة سوداء/بيضاء. يمكن للفلتر السماح باللاتينية فقط أو السيريلية فقط أو مجموعة محددة من الأحرف.
لا، يعمل InputFilter فقط عند إدخال المستخدم أو اللصق من الحافظة. إذا تم تعيين النص برمجيًا عبر setText()، لا يتم تطبيق المرشحات. للتحقق من النص البرمجي، استخدم التحقق عبر TextWatcher أو الفحص الصريح قبل التعيين.
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.