TextWatcher ایک Android انٹرفیس ہے جو EditText اور دیگر TextView میں ریئل ٹائم میں ٹیکسٹ کی تبدیلیوں کو ٹریک کرنے کی اجازت دیتا ہے۔ ڈیولپر کو تین مراحل میں اطلاعات موصول ہوتی ہیں: تبدیلی سے پہلے، تبدیلی کے دوران، اور ٹیکسٹ مواد کی تبدیلی کے بعد۔ Android Developers, 2026 کے مطابق، TextWatcher زیادہ تر ایپلیکیشنز میں ان پٹ کی توثیق، حروف کی گنتی، خودکار تکمیل کے ساتھ تلاش کے نفاذ اور متحرک ٹیکسٹ فارمیٹنگ کے لیے استعمال ہوتا ہے۔ یہ انٹرفیس ان فارمز میں ناگزیر ہے جہاں ہر کلید کے دبانے پر فوری ردعمل کی ضرورت ہوتی ہے۔
اہم نکات
TextWatcher پیکیج android.text کا ایک انٹرفیس ہے جو Editable آبجیکٹ میں ٹیکسٹ کی تبدیلیوں کے بارے میں ایپلیکیشن کو مطلع کرتا ہے۔ ہر حرف کے اندراج، حذف یا تبدیلی کے ساتھ، TextWatcher ترتیب وار تین طریقوں کو کال کرتا ہے، تبدیلیوں کی پوزیشن کے بارے میں معلومات منتقل کرتا ہے۔ یہ ڈیولپر کو اضافی بٹنوں یا ٹرگرز کے بغیر فوری طور پر صارف کے اقدامات پر ردعمل ظاہر کرنے کی اجازت دیتا ہے۔
استعمال کے اہم معاملات میں ریئل ٹائم فیلڈ توثیق شامل ہے: ہر حرف ٹائپ کرتے وقت ای میل کی جانچ کرنا، لمبائی کی حد والے فیلڈ میں باقی حروف کی گنتی کرنا، ڈیباؤنس کے ذریعے تاخیری درخواست کے ساتھ تلاش کو نافذ کرنا۔ TextWatcher ان پٹ فارمیٹنگ کے لیے بھی استعمال ہوتا ہے — مثال کے طور پر، فون نمبر میں خودکار طور پر اسپیس ڈالنا یا تاریخ کے لیے ماسک شامل کرنا۔
Android Developers کے مطابق، TextWatcher 70% ایپلیکیشنز میں موجود ہے جو فارمز کے ساتھ کام کرتی ہیں۔ Material Design Components اور TextInputEditText جیسی لائبریریاں اندرونی طور پر TextWatcher کو خرابی کی حالتوں کے انتظام اور کاؤنٹر ظاہر کرنے کے لیے استعمال کرتی ہیں۔ اس انٹرفیس کے کام کو سمجھنا ہر Android ڈیولپر کے لیے ضروری ہے۔
TextWatcher addTextChangedListener طریقہ کے ذریعے کسی بھی TextView یا EditText آبجیکٹ سے منسلک ہوتا ہے۔ جب صارف کوئی حرف ٹائپ یا حذف کرتا ہے، Android پہلے beforeTextChanged، پھر onTextChanged، اور آخر میں afterTextChanged کو کال کرتا ہے۔ ہر طریقہ کے پیرامیٹرز میں تبدیل شدہ رینج کے بارے میں ڈیٹا ہوتا ہے: شروع کی پوزیشن، حذف شدہ حروف کی تعداد، اور شامل کردہ حروف کی تعداد۔
یہ سمجھنا ضروری ہے کہ afterTextChanged کو کال کرنے کے بعد، Editable آبجیکٹ میں پہلے سے موجودہ قیمت موجود ہوتی ہے۔ لہذا، afterTextChanged میں فیلڈ کا آخری ٹیکسٹ چیک کرنا آسان ہے۔ اس لمحے سے پہلے، ڈیٹا ابھی مکمل طور پر اپڈیٹ نہیں ہوا ہے۔ ڈیولپر اکثر طریقوں کے مقصد میں الجھ جاتے ہیں اور حتمی توثیق کے لیے onTextChanged استعمال کرتے ہیں، جبکہ صحیح انتخاب afterTextChanged ہے۔
ہر حرف کی افزائش، تبدیلی یا حذف کے ساتھ، کال چین مکمل طور پر عمل میں آنے کی ضمانت ہے۔ تاہم، اگر afterTextChanged کے اندر ٹیکسٹ تبدیل کیا جاتا ہے (clear، append، insert کے ذریعے)، TextWatcher تکراری طور پر متحرک ہو جائے گا۔ یہ Android فارمز میں StackOverflowError کی سب سے عام وجہ ہے۔ تکرار کو روکنے کے لیے فلیگ لاک کا استعمال کیا جاتا ہے۔
تینوں طریقوں میں سے ہر ایک ٹیکسٹ تبدیلی کی زندگی کے چکر میں اپنا کردار ادا کرتا ہے۔ beforeTextChanged(CharSequence s, int start, int count, int after) طریقہ تبدیلیاں لاگو کرنے سے پہلے کال کیا جاتا ہے۔ یہ سٹرنگ کی موجودہ حالت، تبدیلی کی شروع کی پوزیشن، حذف ہونے والے حروف کی تعداد، اور شامل کیے جانے والے حروف کی تعداد منتقل کرتا ہے۔ یہاں آپ تبدیلی سے پہلے پچھلی قیمت محفوظ کر سکتے ہیں یا شرائط چیک کر سکتے ہیں۔
onTextChanged طریقہ تبدیلی کے دوران کال کیا جاتا ہے، جب حروف پہلے ہی حذف ہو چکے ہوں لیکن نئے ابھی شامل نہیں ہوئے ہوں۔ پیرامیٹرز: حذف کرنے کے بعد ٹیکسٹ، شروع کی پوزیشن، حذف شدہ حروف کی تعداد، اور شامل کردہ حروف کی تعداد۔ یہ طریقہ اینی میشن یا لاگنگ کے لیے آسان ہے، لیکن اصل آخری ٹیکسٹ کے ساتھ کام کرنے کے لیے نہیں — یہ ابھی جمع نہیں ہوا ہے۔
afterTextChanged طریقہ سب سے زیادہ مانگا جانے والا ہے۔ یہ ایک Editable آبجیکٹ وصول کرتا ہے اور تبدیلیاں مکمل طور پر لاگو ہونے کے بعد کال کیا جاتا ہے۔ اس طریقہ میں آپ فیلڈ کی آخری قیمت پڑھ سکتے ہیں، توثیق کر سکتے ہیں، UI اپڈیٹ کر سکتے ہیں اور ٹیکسٹ تبدیل کر سکتے ہیں (تکرار کی وجہ سے احتیاط کے ساتھ)۔
ایک عملی مثال — ان پٹ فیلڈ کے لیے حروف کا کاؤنٹر جو ہر ٹیکسٹ تبدیلی کے ساتھ اپڈیٹ ہوتا ہے۔ ایسا عنصر اکثر فیڈ بیک فارمز، پوسٹس اور لمبائی کی حد والے پیغامات میں پایا جاتا ہے۔ TextWatcher کے ذریعے نفاذ میں چند سطریں لگتی ہیں اور تیسری پارٹی کی لائبریری کی ضرورت نہیں ہوتی۔
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 طریقہ Editable قسم کے s پیرامیٹر کے ذریعے فیلڈ کا موجودہ مواد وصول کرتا ہے۔ ٹیکسٹ کی لمبائی ایک علیحدہ TextView میں اپڈیٹ ہوتی ہے۔ اس معاملے میں، صرف counterText میں ترمیم کی جاتی ہے، EditText خود نہیں، اس لیے کوئی لوپ نہیں بنتا۔ 200 حروف کی حد کے لیے، حد سے تجاوز کرنے کے بعد ان پٹ کو اضافی طور پر بلاک کیا جا سکتا ہے۔
beforeTextChanged اور onTextChanged طریقے خالی رہتے ہیں، کیونکہ لمبائی کی گنتی کے لیے آخری حالت کافی ہے۔ اگر ہر تبدیلی کو لاگ کرنے کی ضرورت ہو، تو onTextChanged میں کوڈ شامل کیا جا سکتا ہے۔ یہ لچک TextWatcher کو ٹیکسٹ ان پٹ کے کسی بھی منظر نامے کے لیے ایک عالمگیر ٹول بناتی ہے۔
ریئل ٹائم توثیق UX کو نمایاں طور پر بہتر کرتی ہے: صارف جمع کرانے کے بٹن پر کلک کرنے کے بعد نہیں، بلکہ غلط قیمت درج کرنے کے فوراً بعد خرابی دیکھتا ہے۔ TextWatcher ای میل، پاس ورڈ، فون نمبر اور دیگر فیلڈز کی فوری جانچ کی اجازت دیتا ہے۔ نتیجہ EditText پر setError کے ذریعے یا خرابی کے پیغام کے ساتھ علیحدہ TextView کے ذریعے ظاہر ہوتا ہے۔
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(...) {}
})
}
مثال ای میل چیک کرنے کے لیے Android SDK سے بلٹ ان Patterns.EMAIL_ADDRESS استعمال کرتی ہے۔ اگر ٹیکسٹ خالی نہیں ہے اور پیٹرن سے میل نہیں کھاتا، تو error پراپرٹی کے ذریعے فیلڈ پر خرابی سیٹ کی جاتی ہے۔ درست ان پٹ پر خرابی صاف ہو جاتی ہے۔ خالی فیلڈ پر توثیق نہ چلانا ضروری ہے — صارف نے ابھی ٹائپ کرنا شروع نہیں کیا ہو گا، اور خرابی کا پیغام قبل از وقت ہو گا۔
پاس ورڈز اور فون نمبرز کے لیے، کسٹم ریگولر ایکسپریشنز یا مخصوص لائبریریاں استعمال کی جاتی ہیں۔ مثال کے طور پر، پاس ورڈ کی پیچیدگی چیک کرنے کے لیے ہندسوں، بڑے اور چھوٹے حروف کی تعداد گنی جا سکتی ہے۔ TextWatcher ریئل ٹائم میں پاس ورڈ کی طاقت کے اشارے کو اپڈیٹ کرنے کی اجازت دیتا ہے، جو رجسٹریشن کنورژن کو مثبت طور پر متاثر کرتا ہے۔
پہلی اور سب سے اہم غلطی تکراری کال ہے۔ اگر afterTextChanged کے اندر اسی EditText کا ٹیکسٹ تبدیل کیا جائے (s.clear()، s.append() یا s.insert() کے ذریعے)، TextWatcher دوبارہ متحرک ہو جائے گا۔ یہ ایک لامتناہی لوپ بناتا ہے جو StackOverflowError پر ختم ہوتا ہے۔ حل isUpdating فلیگ لاک استعمال کرنا یا یہ چیک کرنا ہے کہ آیا ٹیکسٹ واقعی تبدیل ہوا ہے۔
دوسرا عام مسئلہ میموری لیک ہے۔ TextWatcher ایک گمنام کلاس کے ذریعے Activity یا Fragment کا مضمر حوالہ رکھتا ہے۔ اگر View تباہ ہونے پر listener نہ ہٹایا جائے، کوڑا کرکٹ جمع کرنے والا میموری خالی نہیں کر سکتا۔ حل لائف سائیکل اجزاء استعمال کرنا یا onDestroyView میں واضح طور پر removeTextChangedListener کال کرنا ہے۔
تیسری غلطی غلط طریقہ استعمال کرنا ہے۔ کچھ ڈیولپر afterTextChanged کا انتظار کیے بغیر onTextChanged میں حتمی توثیق کرتے ہیں۔ onTextChanged میں، ٹیکسٹ ابھی مکمل طور پر اپڈیٹ نہیں ہوا ہے، اور آخری قیمت پڑھنے پر غلط ڈیٹا واپس آ سکتا ہے۔ صحیح طریقہ یہ ہے کہ آخری ٹیکسٹ کو پڑھنے اور چیک کرنے کی تمام منطق afterTextChanged میں ہونی چاہیے۔
| طریقہ | کال کا وقت | مقصد | کیا آخری ٹیکسٹ پڑھ سکتے ہیں؟ |
|---|---|---|---|
| beforeTextChanged | تبدیلی سے پہلے | پچھلی حالت محفوظ کریں | ہاں |
| onTextChanged | تبدیلی کے دوران | لاگنگ، اینی میشن | نہیں |
| afterTextChanged | تبدیلی کے بعد | توثیق، گنتی، UI اپڈیٹ | ہاں |
چوتھی غلطی متعدد TextWatcher اضافہ ہے۔ اگر ایک ہی EditText کے لیے addTextChangedListener کئی بار کال کیا جائے، تو تمام listeners ایک ہی تبدیلی پر کارروائی کریں گے۔ متحرک View اضافے والے فارمز میں، یہ ڈپلیکیٹ چیک اور غیر متوقع رویے کا باعث بنتا ہے۔ ہمیشہ چیک کریں کہ آیا listener پہلے شامل کیا گیا ہے، یا ایک ہی انسٹنس استعمال کریں۔
اکثر پوچھے گئے سوالات
OnTextChanged ٹیکسٹ تبدیلی کے لمحے کال کیا جاتا ہے جب نئے حروف ابھی شامل نہیں ہوئے ہیں۔ یہ طریقہ اینی میشن اور لاگنگ کے لیے موزوں ہے۔ AfterTextChanged تبدیلیاں مکمل طور پر لاگو ہونے کے بعد کال کیا جاتا ہے اور Editable پیرامیٹر کے ذریعے آخری ٹیکسٹ تک رسائی فراہم کرتا ہے۔ توثیق اور قیمتیں پڑھنے کے لیے afterTextChanged استعمال کریں۔
Boolean قسم کا فلیگ لاک استعمال کریں، جو afterTextChanged کے اندر ٹیکسٹ تبدیل کرنے سے پہلے true پر سیٹ ہوتا ہے۔ طریقہ کے شروع میں فلیگ چیک کریں: اگر true ہے — باہر نکلیں۔ متبادل طور پر، پرانی اور نئی قیمتوں کا موازنہ کریں اور صرف حقیقی فرق ہونے پر ٹیکسٹ تبدیل کریں۔
ہاں، لازمی طور پر۔ گمنام TextWatcher کلاس Closure کے ذریعے Activity کا حوالہ رکھتی ہے۔ اگر listener نہ ہٹایا جائے، Activity کوڑا کرکٹ جمع کرنے والے کے ذریعے جمع نہیں کی جا سکتی۔ Fragment کے لیے onDestroyView یا Activity کے لیے onDestroy میں ہمیشہ removeTextChangedListener کال کریں۔
ہاں، لیکن احتیاط کے ساتھ۔ RecyclerView میں، ViewHolders دوبارہ استعمال ہوتے ہیں اور پچھلی پوزیشن کا TextWatcher فعال رہ سکتا ہے۔ onBindViewHolder طریقہ میں نیا سیٹ کرنے سے پہلے ہمیشہ پرانا TextWatcher ہٹائیں۔ listener کا حوالہ محفوظ کرنے کے لیے ٹیگز یا علیحدہ ViewHolder فیلڈز استعمال کریں۔
تلاش کے فیلڈ کے لیے، ڈیباؤنس (تاخیر) کے ساتھ afterTextChanged استعمال کریں۔ 300-500 ms کا ٹائمر لاگو کریں جو ہر نئی ٹیکسٹ تبدیلی پر ری سیٹ ہوتا ہے۔ یہ ہر کلید دبانے پر سرور کو درخواست بھیجنے سے روکتا ہے اور API لوڈ کو کم کرتا ہے۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں