كيفية تعطيل OnItemectedListener للاستدعاء عند تعيين عنصر محدد حسب الرمز
سؤال
فقط أتساءل كيف تتعامل مع المشكلة التالية: يتم حساب النتيجة اعتمادًا على عنصرين محددين. للتعامل مع أشياء واجهة المستخدم ، أي مستخدم يختار عنصرًا جديدًا في أحد المغازل ، أقوم بتثبيت مستمع باستخدام setOnItemSelectedListener
للدوران في بلدي onCreate()
طريقة النشاط.
الآن: هذا يعمل ، بالطبع ، بخير. عمل المستمع هو تشغيل حساب جديد للنتيجة.
المشكلة: لأنني اعتترض onPause()
onResume()
لحفظ/استعادة الحالة الأخيرة ، حصلت على طريقة مجموعات العنصر المحدد لهذين المغازلين برمجيا كما هو الحال هنا:
startSpinner.setSelection(pStart);
destSpinner.setSelection(pDest);
هاتان المكالمتان تستدعي المستمعين أيضًا! يتم استدعاء طريقة الحساب الخاصة بي للنتيجة بالإضافة إلى الإخطار بمجموعة نتائج جديدة مرتين هنا!
إن النهج المباشر الغبي لهذا هو أن يكون هناك متغير منطقي تعطيل مهما كان المستمع في الداخل ، قم بإعداده قبل تعيين العناصر المحددة وإعادة تعيينه بعد ذلك. تمام. ولكن هل هناك طريقة أفضل ؟؟
لا أريد أن يتم استدعاء المستمعين من قبل الكود - الإجراءات ، فقط عن طريق إجراءات المستخدم! :-(
كيف تقوم بذلك؟ شكرًا!
المحلول
لدي حل أسهل ، وأعتقد ، أفضل. بما أنني اضطررت إلى تحديث المغازل حتى بعد التهيئة ، فهذا نهج أكثر عامة. يرجى إحالة الإجابة المقبولة:
نصائح أخرى
حل أنظف ، في رأيي ، للتمييز بين التغييرات البرنمجية والمستخدم هو ما يلي:
أنشئ المستمع الخاص بك للدوران باعتباره onTouchListener و OnItemSelectedRister
public class SpinnerInteractionListener implements AdapterView.OnItemSelectedListener, View.OnTouchListener {
boolean userSelect = false;
@Override
public boolean onTouch(View v, MotionEvent event) {
userSelect = true;
return false;
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if (userSelect) {
// Your selection handling code here
userSelect = false;
}
}
}
أضف المستمع إلى تسجيل الدوران لكلا نوعين الأحداث
SpinnerInteractionListener listener = new SpinnerInteractionListener();
mSpinnerView.setOnTouchListener(listener);
mSpinnerView.setOnItemSelectedListener(listener);
وبهذه الطريقة ، سيتم تجاهل أي مكالمات غير متوقعة إلى طريقة معالجك بسبب التهيئة أو إعادة التهيئة.
حسنًا ، لقد عملت بالطريقة التي أريدها الآن.
الشيء الذي يجب فهمه هنا (ولم أفعل عندما كنت أكتب هذا السؤال ...) هو أن كل شيء في Android يعمل في موضوع واحد - موضوع واجهة المستخدم.
المعنى: على الرغم من أنك وضعت قيم Spinner هنا وهناك: يتم تحديثها فقط (بصريًا) و يتم استدعاء مستمعيهم فقط بعد، بعدما جميع الطرق التي تكون فيها حاليًا (مثل onCreate
, onResume
أو أيا كان) انتهى.
هذا يسمح بما يلي:
- الحفاظ على المواضع المحددة في متغيرات الحقل. (مثل
currentPos1
,currentPos2
) - المستمعون
onItemSelectedListener()
استدعاء طريقة مثلrefreshMyResult()
أو أيا كان. - عند تعيين المواضع برمجيًا ، قم بتعيين المغازل و استدعاء طريقة التحديث الخاصة بك يدويًا بعد ذلك.
ال refreshMyResult()
الطريقة تبدو هكذا:
int newPos1 = mySpinner1.getSelectedItemPosition();
int newPos2 = mySpinner2.getSelectedItemPosition();
// only do something if update is not done yet
if (newPos1 != currentPos1 || newPos2 != currentPos2) {
currentPos1 = newPos1;
currentPos2 = newPos2;
// do whatever has to be done to update things!
}
نظرًا لأنه سيتم استدعاء المستمعين لاحقًا - وبحلول ذلك الوقت ، تم تحديث الموقف الذي تم تذكره في CurrentPos بالفعل - لن يحدث شيء ولن يحدث أي تحديث غير ضروري لأي شيء آخر. عندما يختار المستخدم قيمة جديدة في أحد المغازل ، سيتم تنفيذ التحديث وفقًا لذلك!
هذا هو! :-)
آه - شيء آخر: الإجابة على سؤالي هي: لا. لا يمكن تعطيل المستمعين (بسهولة) وسيتم استدعاؤهم كلما تم تغيير قيمة.
أضف أولاً قيم منطقية لإيقاف مكالمة مستمع الدوار
Boolean check = false;
ثم تضيف على مستمع اللمس وعلى العنصر انقر فوق المستمع مثل الرمز أدناه
holder.filters.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
check = true;
return false;
}
});
holder.filters.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
@Override
public void onItemSelected(AdapterView<?> parent, View arg1, int position, long id)
{
flag = filterids.get(position);
if(check)
{
check = false;
new Applyfilters().execute(flag,"3");
}else{
}
}
@Override
public void onNothingSelected(AdapterView<?> arg0)
{
// TODO Auto-generated method stub
}
});
إنه عمل بسيط جيد لوقف مكالمة الخادم عدة مرات.
من السهل جدًا الاتصال بـ Spinner.setSelection(int position, boolean animate)
الطريقة مع false
لذلك لن يتفاعل المستمعون على التغيير.
Spinner.SetSelection (int position ، Boolean Amany) لا يؤدي إلى المستمع في 4.3
لقد قمت بإنشاء مكتبة تساعد للجميع ، والتي لا داعي لاتصال عنصر Onclick في Spinner على سبيل المثال:
spinner.setSelection(withAction,position);
عندما يكون العمل هو علم منطقي ، يتم استخدامه للاتصال أو عدم إجراء عنصر
رابط على جيثب:https://github.com/scijoker/spinner2
أضف ال OnItemSelectedListener
لكل غزل بعد، بعدما لقد حددت أي قيمة سابقة في onResume
.
عند استخدام spinner.setselection (الموضع) ، فإنه يقوم دائمًا بتنشيط setOnitemSelectedListener ()
لتجنب إطلاق الرمز مرتين أستخدم هذا الحل:
private mIsSpinnerFirstCall=true;
...
Spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
//If a new value is selected (avoid activating on setSelection())
if(!mIsSpinnerFirstCall) {
// Your code goes gere
}
mIsSpinnerFirstCall = false;
}
public void onNothingSelected(AdapterView<?> arg0) {
}
});
هذا الحل صالح عندما تكون متأكدًا من أن spinner.setselection (الموضع) المستخدمة. أيضًا ، من المهم تعيين MissPinnerfirstCall = صحيح في كل مرة قبل استخدام spinner.setselection (الموضع)
حلي سهل للغاية. تهيئة أولاً متغير منطقي عالمي.
boolean shouldWork = true;
ثم استخدم الكود أدناه في طريقة onCreate ().
Spinner spinner = findViewById(R.id.spinner);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView adapter, View v, int i, long lng) {
if (shouldWork) {
// Do your actions here
}
else
shouldWork = true;
}
public void onNothingSelected(AdapterView<?> parentView) {
}
});
يمكنك الآن استخدام طريقة setSelection في Everwaye دون استدعاء طريقة OnItemSelected () بموجب الرمز أدناه.
shouldWork = false;
spinner.setSelection(0);
This following method will help you to stop invoking automatically the selection listener
yourspinnerobj.post(new Runnable() {
@Override
public void run() {
yourspinnerobj.setOnItemSelectedListener(yourspinnerlistener);
}
});