كيفية تعطيل OnItemectedListener للاستدعاء عند تعيين عنصر محدد حسب الرمز

StackOverflow https://stackoverflow.com/questions/2297601

  •  21-09-2019
  •  | 
  •  

سؤال

فقط أتساءل كيف تتعامل مع المشكلة التالية: يتم حساب النتيجة اعتمادًا على عنصرين محددين. للتعامل مع أشياء واجهة المستخدم ، أي مستخدم يختار عنصرًا جديدًا في أحد المغازل ، أقوم بتثبيت مستمع باستخدام 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);
                }
            });
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top