سلام ووقت بخیر
به قطعه کد زیر توجه کنید
من یک EditText دارم که نوعش numberDecimal است منتها چون روی دیتا عملیات انجام میشه میخوام هروقت کار بر فیلد رو پاک کرد یعنی مقدارش null شد صفرش کنه تا خطا نده منتها چون لوپ میشه خطا میده چطور میتونم همینجا صفر نمایش بده
EditText et=(EditText) findViewById(R.id.many_et);
et.addTextChangedListener(new TextWatcher() {
private Double many_old = 0.0;
@Override
public void onTextChanged(CharSequence s, int start, int before,int count) {
try {
if(s==null)
et.setText("0.0");
myFunction();
}
catch (NumberFormatException e) {
Log.e(TAG, "error onTextChanged: " + s.toString());
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
this.many_old = Double.valueOf(et.getText().toString());
}
@Override
public void afterTextChanged(Editable s) {
}
});
الان مشکل کدی که گذاشتین چیه؟
چون در خط
et.setText("0.0");
دچار خطا میشه (بدلیل لوپ شدن چون مجددا بدلیل درخواست تغییر این متد میخواهد اجرا شودولی چرا خطا!) درنتیجه فانکشن من اجرا نمیشه ومقدار صفر هم در فیلد et نمایش داده نمیشه
میتونید یه فیلد public از نوع boolean بگذارین و هرجا خودتون دستی چیزی رو ویرایش میکنید، اون فیلد رو true کنید. توی Listener خودتون اون فیلد رو چک کنید اگه true بود یعنی خودتون تغییر دادین و دیگه دستورات Listener رو اجرا نکنید. فقط در انتهای Listener دوباره false کنید تا اگه کاربر ویرایش کرد، دوباره اجرا بشه.
EditText et = (EditText) findViewById(R.id.many_et);
et.addTextChangedListener(new TextWatcher() {
private Double many_old = 0.0;
private boolean manualEdit = false;
@Override
public void onTextChanged(CharSequence s, int start, int before,int count) {
if(!manualEdit) {
try {
if(s==null) {
et.setText("0.0");
manualEdit = true;
}
myFunction();
}
catch (NumberFormatException e) {
Log.e(TAG, "error onTextChanged: " + s.toString());
}
manualEdit = false;
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
this.many_old = Double.valueOf(et.getText().toString());
}
@Override
public void afterTextChanged(Editable s) {
}
});
وقتی روی
et.setText("0.0");
خطا اتفاق بیفته دیگه به خط
manualEdit = true;
نمیرسه که بخواد اجرا شه
ولی بازم با این روش اجرا میکنم البته پس بهتره جای این دوخط عوض شه
-------------------
بله همونطور که حدس زدم درست نشد نمیدونم چرا ولی داخل این متد به هیچ وجه مجوز تغییر نمیده تا ما بخواهیم با ترفندی اینکار رو انجام بدیم
من حدس میزنم باید داخل afterTextChanged کدی برای اینکار بنویسم وگرنه هیچ جای دیگری پیدا نکردم ولی نمیدونم چطور از پارامترش استفاده کنم
(منظورم Editable s) است
اگر از خود et.setText استفاده کنم که با همون خطا مواجه میشم
روی onFocusChanged یک listener نصب کنید ببینید درست میشه؟
نه ممکنه کاربر فوکوس رو تغییر نده وبلافاصله پس از پاک کردن فیلد مجددا تغییر بده درنتیجه باخطا مواجه میشه
مشکل این textChange همینه که به ازای هر تغییر حرف به حرف اتفاق میفته مثلا اگر من عدد 10 را وارد بخوام بکنم
این متد یکبار برای 1 اجرا میشه ویکبار برای10 در حالیکه من نیاز دازم مثلا تابع myFunction فقط یکبار اجرا بشه
به ناچار مجبور شدم فیلد many_old را در beforeTextChange بذارم تا عمل قبلی رو خنثی کنه
هفت خان رستم یه برای خودش
-----------------
این مشکل رو برای مقادیر منفی هم دارم میخوام اگه مثلا منهای 10 زد صفر در نظر بگیره سعی کردم نوع فیلد رو بدون علامت در نظر بگیرم ولی کار نکرد توی این حالت حتما باید نمایش فیلدهم صفر بشه چون کاربر عادت داره مقدار نول رو خودش صفر در نظر بگیره ولی عدد منفی رو که دیگه نه !
خوب موضوع اینه که رویداد Change عملاً با تایپ هر چیزی اتفاق میفته و عملکرد اندروید در این مورد، غیر طبیعی نیست. من موردی که گفتم (استفاده از فیلد) رو تست کردم و مشکلی نبود. میتونید یه کار دیگه هم انجام بدین با کمک Thread و هر چند لحظه یکبار مقدار کادر متن رو بررسی کنید اگه از آخرین اجرای Thread تا حالا تغییر کرده بود، عملیاتی که میخواین رو اجرا کنید. اینطوری با تنظیم Thread.Sleep میتونید روی سرعت تایپ کنترل بیشتری داشته باشین.