TextWatcher: ما هو، واجهة TextWatcher وتنفيذها في Android

المؤلف: IT Sectr نُشر: 2026-07-08 وقت القراءة: 6 دق

TextWatcher هي واجهة Android تتيح تتبع تغييرات النص في EditText و TextView الأخرى في الوقت الفعلي. يتلقى المطور إشعارات في ثلاث مراحل: قبل التغيير، أثناء التغيير، وبعد التغيير لمحتوى النص. وفقًا لـ Android Developers, 2026، يتم استخدام TextWatcher في معظم التطبيقات للتحقق من صحة الإدخال، عدد الأحرف، تنفيذ البحث مع الإكمال التلقائي، والتنسيق الديناميكي للنص. الواجهة لا غنى عنها في النماذج التي تتطلب ردًا فوريًا على كل ضغطة مفتاح.

الخلاصة

  • TextWatcher هي واجهة مدمجة في Android SDK للاستماع إلى تغييرات النص في TextView و EditText.
  • تحتوي الواجهة على ثلاث طرق: beforeTextChanged، onTextChanged و afterTextChanged، كل منها مسؤول عن مرحلته الخاصة من التغيير.
  • طريقة afterTextChanged هي الأكثر ملاءمة للتحقق من صحة الحقل بعد انتهاء المستخدم من الإدخال.
  • الاستدعاء التكراري هو خطأ شائع: تغيير النص داخل TextWatcher يؤدي إلى حلقة لا نهائية.
  • TextWatcher يُستخدم في حقول البحث، التحقق من صحة النماذج، عدد الأحرف، والتنسيق التلقائي لأرقام الهواتف.

ما هو TextWatcher ولماذا هو مطلوب؟

TextWatcher هي واجهة من حزمة android.text تُشعر التطبيق بتغييرات النص في كائنات Editable. مع كل إدخال أو حذف أو استبدال حرف، تستدعي TextWatcher ثلاث طرق بالتسلسل، ناقلة معلومات حول موقع التغييرات. يتيح ذلك للمطور التفاعل مع إجراءات المستخدم فورًا - دون أزرار إضافية أو مشغلات.

تشمل حالات الاستخدام الرئيسية التحقق من صحة الحقول في الوقت الفعلي: التحقق من البريد الإلكتروني أثناء كتابة كل حرف، عدد الأحرف المتبقية في حقل بحد أقصى، تنفيذ بحث مع طلب مؤجل عبر debounce. كما يُستخدم TextWatcher لتنسيق الإدخال - على سبيل المثال، الإدراج التلقائي للمسافات في رقم الهاتف أو إضافة قناع للتاريخ.

وفقًا لـ Android Developers، يتواجد TextWatcher في 70% من التطبيقات التي تعمل مع النماذج. تستخدم مكتبات مثل Material Design Components و TextInputEditText TextWatcher داخليًا لإدارة حالات الخطأ وعرض العدادات. فهم كيفية عمل هذه الواجهة ضروري لكل مطور Android.

كيف تعمل واجهة TextWatcher

يتصل TextWatcher بأي كائن TextView أو EditText عبر طريقة addTextChangedListener. عندما يكتب المستخدم أو يحذف حرفًا، يستدعي Android أولاً beforeTextChanged، ثم onTextChanged، وأخيرًا afterTextChanged. تحتوي معلمات كل طريقة على بيانات حول النطاق المعدل: موضع البداية، عدد الأحرف المحذوفة، وعدد الأحرف المضافة.

من المهم فهم أنه بعد استدعاء afterTextChanged، يحتوي كائن Editable بالفعل على القيمة الحالية. لذلك، من المناسب التحقق من النص النهائي للحقل في afterTextChanged. قبل تلك اللحظة، البيانات لم يتم تحديثها بالكامل بعد. غالبًا ما يخلط المطورون بين الغرض من الطرق ويستخدمون onTextChanged للتحقق النهائي، على الرغم من أن الاختيار الصحيح هو afterTextChanged.

خصائص استدعاء الطرق

مع كل إدراج أو استبدال أو حذف حرف، يتم تنفيذ سلسلة الاستدعاءات بالكامل بشكل مضمون. ومع ذلك، إذا تم تغيير النص داخل afterTextChanged (عبر clear، append، insert)، فسيتم تنشيط TextWatcher بشكل تكراري. هذا هو السبب الأكثر شيوعًا لـ StackOverflowError في نماذج Android. لمنع التكرار، يتم استخدام علامة قفل.

طرق TextWatcher الثلاث: beforeTextChanged، onTextChanged، afterTextChanged

تلعب كل من الطرق الثلاث دورها في دورة حياة تغيير النص. تُستدعى طريقة beforeTextChanged(CharSequence s, int start, int count, int after) قبل تطبيق التغييرات. تنقل الحالة الحالية للسلسلة، موضع بداية التغيير، عدد الأحرف التي يتم حذفها وعددها الذي يتم إضافته. هنا يمكن حفظ القيمة السابقة أو التحقق من الشروط قبل التعديل.

طريقة onTextChanged تُستدعى أثناء التغيير، عندما تم حذف الأحرف بالفعل ولكن لم يتم إدراج الأحرف الجديدة بعد. المعلمات: النص بعد الحذف، موضع البداية، عدد الأحرف المحذوفة، وعدد الأحرف المضافة. هذه الطريقة مناسبة للرسوم المتحركة أو التسجيل، ولكن ليس للعمل مع النص النهائي الفعلي - لم يتم تجميعه بعد.

طريقة afterTextChanged هي الأكثر طلبًا. تتلقى كائن Editable وتُستدعى بعد تطبيق التغييرات بالكامل. في هذه الطريقة يمكن قراءة القيمة النهائية للحقل، إجراء التحقق، تحديث واجهة المستخدم، وتعديل النص (بحذر بسبب التكرار).

مثال تنفيذ TextWatcher لعدد الأحرف

مثال عملي - عداد الأحرف لحقل الإدخال الذي يتم تحديثه مع كل تغيير في النص. غالبًا ما يوجد هذا العنصر في نماذج التعليقات والمنشورات والرسائل ذات الحد الأقصى للطول. التنفيذ عبر TextWatcher يتطلب بضعة أسطر ولا يحتاج إلى مكتبات خارجية.

kotlin
val editText = findViewById<EditText>(R.id.edit_text)
val counterText = findViewById<TextView>(R.id.counter)

editText.addTextChangedListener(object : TextWatcher {
    override fun beforeTextChanged(
        s: CharSequence?, start: Int,
        count: Int, after: Int
    ) {}

    override fun onTextChanged(
        s: CharSequence?, start: Int,
        before: Int, count: Int
    ) {}

    override fun afterTextChanged(s: Editable?) {
        val len = s?.length ?: 0
        counterText.text = "$len / 200"
    }
})

في المثال، تتلقى طريقة afterTextChanged المحتوى الحالي للحقل عبر المعامل s من نوع Editable. يتم تحديث طول النص في TextView منفصل. في هذه الحالة، يتم تعديل counterText فقط، وليس EditText نفسه، لذلك لا تحدث حلقة. للحد الأقصى 200 حرف، يمكن حظر الإدخال الإضافي بعد تجاوزه.

تبقى طريقتا beforeTextChanged و onTextChanged فارغتين، حيث أن الحالة النهائية كافية لعدد الطول. إذا كنت بحاجة إلى تسجيل كل تغيير، يمكن إضافة الكود في onTextChanged. هذه المرونة تجعل TextWatcher أداة عالمية لأي سيناريو إدخال نص.

TextWatcher للتحقق من صحة الحقول في الوقت الفعلي

التحقق في الوقت الفعلي يحسن تجربة المستخدم بشكل كبير: يرى المستخدم الخطأ فور إدخال قيمة غير صحيحة، بدلاً من رؤيته بعد النقر على زر الإرسال. يسمح TextWatcher بالتحقق الفوري من البريد الإلكتروني، كلمة المرور، رقم الهاتف، وحقول أخرى. تظهر النتيجة عبر setError في EditText أو عبر TextView منفصل مع رسالة خطأ.

kotlin
fun validateEmail(emailEditText: EditText) {
    emailEditText.addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(s: Editable?) {
            val email = s?.toString () ?: ""
            if (email.isNotBlank() &&
                !Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
                emailEditText.error = "Invalid email address"
            } else {
                emailEditText.error = null
            }
        }

        override fun beforeTextChanged(...) {}
        override fun onTextChanged(...) {}
    })
}

يستخدم المثال Patterns.EMAIL_ADDRESS المدمج من Android SDK للتحقق من البريد الإلكتروني. إذا كان النص غير فارغ ولا يتطابق مع النمط، يتم تعيين خطأ للحقل عبر خاصية error. عند الإدخال الصحيح، يتم مسح الخطأ. من المهم عدم تشغيل التحقق على حقل فارغ - قد لا يكون المستخدم قد بدأ الإدخال بعد، ورسالة الخطأ ستكون سابقة لأوانها.

لكلمات المرور وأرقام الهواتف، تُستخدم التعبيرات النمطية المخصصة أو المكتبات المتخصصة. على سبيل المثال، للتحقق من تعقيد كلمة المرور، يمكن حساب عدد الأرقام والأحرف الكبيرة والصغيرة. يسمح TextWatcher بتحديث مؤشر قوة كلمة المرور في الوقت الفعلي، مما يؤثر إيجابيًا على تحويل التسجيل.

الأخطاء الشائعة عند العمل مع TextWatcher

الخطأ الأول والأكثر خطورة هو الاستدعاء التكراري. إذا قمت بتغيير نص نفس EditText داخل afterTextChanged (عبر s.clear() أو s.append() أو s.insert())، فسيتم تنشيط TextWatcher مرة أخرى. هذا يخلق حلقة لا نهائية تنتهي بـ StackOverflowError. الحل هو استخدام علامة قفل isUpdating أو التحقق مما إذا كان النص قد تغير بالفعل.

المشكلة الثانية الشائعة هي تسرب الذاكرة. يحتفظ TextWatcher بمرجع ضمني إلى Activity أو Fragment من خلال فئة مجهولة. إذا لم يتم إزالة المستمع عند تدمير العرض، لن يتمكن جامع القمامة من تحرير الذاكرة. الحل هو استخدام مكونات دورة الحياة أو استدعاء removeTextChangedListener صراحةً في onDestroyView.

الخطأ الثالث هو استخدام الطريقة الخاطئة. يقوم بعض المطورين بإجراء التحقق النهائي في onTextChanged، دون انتظار afterTextChanged. في onTextChanged، النص لم يتم تحديثه بالكامل بعد، وقراءة القيمة النهائية قد تعيد بيانات غير صحيحة. النهج الصحيح هو أن كل منطق قراءة النص النهائي والتحقق منه يجب أن يكون في afterTextChanged.

الطريقةوقت الاستدعاءالغرضهل يمكن قراءة النص النهائي؟
beforeTextChangedقبل التغييرحفظ الحالة السابقةنعم
onTextChangedأثناء التغييرالتسجيل، الرسوم المتحركةلا
afterTextChangedبعد التغييرالتحقق، العد، تحديث واجهة المستخدمنعم

الخطأ الرابع هو الإضافة المتعددة لـ TextWatcher. إذا تم استدعاء addTextChangedListener عدة مرات لنفس EditText، فستقوم جميع المستمعين بمعالجة نفس التغيير. في النماذج ذات الإضافة الديناميكية للعروض، يؤدي ذلك إلى تكرار الفحوصات وسلوك غير متوقع. تحقق دائمًا مما إذا كان المستمع قد أضيف بالفعل، أو استخدم مثيلًا واحدًا.

الأسئلة الشائعة

ما الفرق بين onTextChanged و afterTextChanged؟

OnTextChanged يُستدعى في لحظة تغيير النص عندما لم تتم إضافة الأحرف الجديدة بعد. هذه الطريقة مناسبة للرسوم المتحركة والتسجيل. AfterTextChanged يُستدعى بعد تطبيق التغييرات بالكامل ويتيح الوصول إلى النص النهائي عبر معامل Editable. للتحقق وقراءة القيم، استخدم afterTextChanged.

كيف أتجنب الاستدعاء التكراري لـ TextWatcher؟

استخدم علامة قفل من نوع Boolean، يتم تعيينها إلى true قبل تغيير النص داخل afterTextChanged. تحقق من العلامة في بداية الطريقة: إذا كانت true - اخرج. بدلاً من ذلك، يمكن مقارنة القيم القديمة والجديدة وتغيير النص فقط عند وجود اختلاف فعلي.

هل أحتاج إلى إزالة TextWatcher عند تدمير Activity؟

نعم، بالتأكيد. الفئة المجهولة TextWatcher تحتفظ بمرجع إلى Activity من خلال الإغلاق. إذا لم تتم إزالة المستمع، لا يمكن لـ Activity أن يتم جمعها بواسطة جامع القمامة. استدعِ دائمًا removeTextChangedListener في onDestroyView لـ Fragment أو في onDestroy لـ Activity.

هل يمكن استخدام TextWatcher في RecyclerView؟

نعم، ولكن بحذر. في RecyclerView، يتم إعادة استخدام ViewHolders، وقد يظل TextWatcher من موضع سابق نشطًا. قم دائمًا بإزالة TextWatcher القديم قبل تعيين واحد جديد في طريقة onBindViewHolder. استخدم الوسوم أو حقول منفصلة في ViewHolder لتخزين مرجع المستمع.

أي طريقة هي الأفضل للبحث مع الإكمال التلقائي؟

لحقل البحث، استخدم afterTextChanged مع debounce (تأخير). قم بتنفيذ مؤقت 300-500 مللي ثانية يتم إعادة تعيينه مع كل تغيير جديد في النص. هذا يمنع إرسال طلب إلى الخادم عند كل ضغطة مفتاح ويقلل من تحميل API.

الملخص

  • TextWatcher هي واجهة Android لتتبع تغييرات النص في EditText و TextView، تنفذ ثلاث طرق استدعاء.
  • طريقة afterTextChanged هي الخيار الأمثل للتحقق وقراءة النص النهائي بعد التغييرات.
  • الاستدعاء التكراري هو الخطر الرئيسي لـ TextWatcher، ويتم منعه بواسطة علامة قفل.
  • إزالة المستمع إلزامية لمنع تسرب الذاكرة عند تدمير Activity أو Fragment.
  • التحقق في الوقت الفعلي مع TextWatcher يحسن تجربة المستخدم ويسمح بإظهار الأخطاء فورًا.
  • Debounce ضروري عند تنفيذ البحث والإكمال التلقائي لتقليل تحميل الخادم.
  • اختيار الطريقة الصحيحة هو مفتاح التشغيل المستقر: beforeTextChanged لحفظ الحالة، onTextChanged للسجلات، afterTextChanged للتحقق النهائي.

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا